Disassembling an old .COM file. Stuck within 48 bytes. Endian problem?
Asked Answered
E

1

5

I had an old game... Starflight. I think it came out in '86. Good ol' IBM PC jr days. I figured I'd break out a disassembler and see how it worked. I can see in the little that I've decoded, code size was optimized for sure... but I ended up jumping to an address that is outside of the file. That makes no sense.

I added the comments in below listing; they're my "thoughts".

Until other files are loaded with, I assume, int 0x3d or int 0x0f... since all segment registers point to the same memory segment.... and that segment is the code segment, the .COM file, every memory reference or jump should stay within the file. Yes?

Starflt.com

00000000 FA                       CLI                     ;Prevent interrupts
00000001 8CC8                     MOV AX,CS               ;Copy code segment to all segments
00000003 8ED0                     MOV SS,AX
00000005 8EC0                     MOV ES,AX
00000007 8ED8                     MOV DS,AX
00000009 BE2901                   MOV SI,word 0x0129      ;SI = 0x0129
0000000C 8B7C02                   MOV DI,word [SI+0x02]   ;DI = 0x3c15 (SI+2)
0000000F 47                       INC DI
00000010 47                       INC DI                  ;DI = 0x3c17
00000011 BB0507                   MOV BX,word 0x0705      ;BX = 0x0705
00000014 8B1F                     MOV BX,word [BX]        ;BX = 0xa924
00000016 81C30001                 ADD BX,word 0x0100      ;BX = 0xaa24
0000001A 8BE3                     MOV SP,BX               ;SP = 0xaa24 (0x0e41)
0000001C 81C38000                 ADD BX,word 0x0080      ;BX = 0xaaa4
00000020 8BEB                     MOV BP,BX               ;BP = 0xaaa4 (0x0bae)
00000022 FB                       STI                     ;Restore Interrupts
00000023 FC                       CLD                     ;Clear direction flag
00000024 AD                       LODSW                   ;AX = DS:SI = 0xfa13
00000025 8BD8                     MOV BX,AX               ;BX = 0xfa13
00000027 FF27                     JMP word [BX]           ;Past COM EOF (0xd3a7)

Memory:

00000705 24                       byte 0x24 '$'
00000706 A9                       byte 0xA9 '©'

00000129 13                       byte 0x13
0000012A FA                       byte 0xFA 'ú'
0000012B 15                       byte 0x15
0000012C 3C                       byte 0x3C '<'

0000AA24 41                       byte 0x41 'A'
0000AA25 0E                       byte 0x0E

0000AAA4 AE                       byte 0xAE '®'
0000AAA5 0B                       byte 0x0B
Erminna answered 28/8, 2020 at 9:2 Comment(2)
Small world. IDK if you recognize that nice blue color on my shoulders. (Schlumberger) I just got my master's in CS. Just have to convince someone I'm worth my salt.Erminna
How can you disassembled a COM file in a 32/64-bit CPU? Or have you done it in an old 16-bit computer?Bottrop
I
8

The program you are disassembling is a DOS COM program. You generally have the right idea but your memory offsets aren't correct. A DOS COM program is loaded into memory starting at a free segment in memory at offset 0x100 within that segment. The first 0x100 bytes are the DOS Program Segment Prefix (PSP). You are disassembling from offset 0x0000 and as a consequence are using the wrong memory addresses in an attempt to decode the COM program.

It is unclear what disassembler you are using, If you were to use ndisasm you can change the origin point using the -o option. If you aren't actually using ndisasm you will have to tell the disassembler you are using that you want an origin point of 0x0100 instead of 0x0000. In the case of ndisasm you can use:

ndisasm -o 0x100 -b16 Starflt.com

I found a copy of Starflight online and it appears to be similar code to yours. The output I get using -o 0x100 is:

00000100  FA                cli
00000101  8CC8              mov ax,cs
00000103  8ED0              mov ss,ax
00000105  8EC0              mov es,ax
00000107  8ED8              mov ds,ax
00000109  BE2901            mov si,0x129       ; si = 0x129
0000010C  8B7C02            mov di,[si+0x2]    ; di = 0x078a
0000010F  47                inc di
00000110  47                inc di             ; di = 0x078c
00000111  BB0507            mov bx,0x705
00000114  8B1F              mov bx,[bx]        ; bx = 0xd4b6
00000116  81C30001          add bx,0x100       ; bx = 0xd5b6
0000011A  8BE3              mov sp,bx          ; sp = 0xd5b6
0000011C  81C38000          add bx,0x80        ; bx = 0xd636
00000120  8BEB              mov bp,bx          ; bp = 0xd636
00000122  FB                sti
00000123  FC                cld
00000124  AD                lodsw              ; ds:si = ds:0x129 . ax = 0x0937
                                               ; si=si+2, si=0x12B 
00000125  8BD8              mov bx,ax          ; bx = 0x0937
00000127  FF27              jmp [bx]           ; jmp to cs:0x224c 
00000129  37                aaa
0000012A  098A0700          or [bp+si+0x7],cx
[snip]
00000704  F7B6D4E6          div word [bp-0x192c]
[snip]
00000937  4C                dec sp
00000938  22DB              and bl,bl
[snip]
0000224C  43                inc bx             ; Execution will continue here
0000224D  43                inc bx
0000224E  4D                dec bp
0000224F  4D                dec bp
00002250  897600            mov [bp+0x0],si
00002253  8BF3              mov si,bx
00002255  AD                lodsw
00002256  8BD8              mov bx,ax
00002258  FF27              jmp [bx]

As you can see the jmp [bx] ultimately starts executing at cs:0x224c which happens to be in memory for this program.

I'd recommend getting ahold of Turbo Debugger and use a DOS emulator like DOSBox if you wish to step through old 16-bit real mode code like this. Starflight will run in DOSBox.

Immoralist answered 28/8, 2020 at 12:9 Comment(4)
Thanks. I did grab DOSBox and have been playing for a few hours. :D I looked and found TaTraDAS for disassembly. I also used the "online disassembler." Both came out with the same instructions. Figured it was my brain grabbing the wrong bytes. The "ODA" can do offsets as expected. Haven't really figured out TDAS. I spent some time in VS17 with inline assembler to see which ones to grab. Failed. TYVM. I am on the right track now.Erminna
@NolanRobidoux : I was able to use the online disassembler and they call it the base address (not the origin point, same thing though). When I went to disassemble it, it did look correct. Likely every disassembler you will find will have an option to change the VMA/Base Address/Origin Point.Immoralist
@NolanRobidoux onlinedisassembler.com/odaweb/Exbuh1Ra/0 was the output I could render. I originally chose machine architecture type i386 and then changes it to intel syntax and to decode as i8086. I then had to right mouse click the disassembly window on the first instruction and select data->code for it to properly disassemble the raw data.Immoralist
Yup. All set there. The super simple stuff is usually what trips me up. I knew of the 0x100 base from my wiki reading. Just apparently not how to apply it. Similar stuff happens all the time for me. Spent hours years ago figuring out why I couldn't program a Diffie Hellman KEX between Java and Erlang (just got +10 this morning on it; fresh in my mind) because I just glossed over "two's complement" in Java's BigInt documentation.Erminna

© 2022 - 2024 — McMap. All rights reserved.