Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 884
Nolan Robidoux Avatar asked Aug 28 '20 09:08

Nolan Robidoux


1 Answers

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.

like image 198
Michael Petch Avatar answered Sep 27 '22 21:09

Michael Petch