当拆解从这样的代码编译的旧的.com可执行文件时:
.model tiny ; com program
.code ; code segment
org 100h ; code starts at offset 100h
main proc near
mov ah,09h ; function to display a string
mov dx,offset message ; offset ofMessage string terminating with $
int 21h ; dos interrupt
mov ah,4ch ; function to terminate
mov al,00
int 21h ; Dos Interrupt
endp
message db "Hello World $" ; Message to be displayed terminating with a $
end main
以十六进制表示如下:
B4 09 BA 0D 01 CD 21 B4 4C B0 00 CD 21 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 24
反汇编程序如何知道代码的结束位置以及字符串“Hello world”的开始?
答案 0 :(得分:1)
反汇编程序不知道代码的结束位置以及数据在.com
文件中的起始位置,因为在.com
文件中没有这样的区别。在.com
文件中,所有内容都加载到同一个段中,并且DOS在实模式下运行并且根本没有任何类型的内存保护,例如,您可以编写看起来像常规文本的混淆代码并跳转到其中你的代码。例如(可能崩溃DOS,尚未测试):
_start: jmp hello
hello:
db "Hello World!"
ret
所以db "Hello World $"
是完全有效的16位代码(在Linux中udis86 disassembler library for x86 and x86-64附带udcli
反汇编程序检查:
$ echo `echo 'Hello World $' | tr -d "\n" | od -An -t xC` | udcli -x -16
0000000000000000 48 dec ax ; H
0000000000000001 656c insb ; el
0000000000000003 6c insb ; l
0000000000000004 6f outsw ; o
0000000000000005 20576f and [bx+0x6f], dl ; <space>Wo
0000000000000008 726c jb 0x76 ; rl
000000000000000a 642024 and [fs:si], ah ; d<space>$
但是,db 0x64 0x20 0x24
无效32位或64位代码。
这是db "Hello World! $"
的32位反汇编:
$ echo `echo 'Hello World $' | tr -d "\n" | od -An -t xC` | udcli -x -32
0000000000000000 48 dec eax ; H
0000000000000001 656c insb ; el
0000000000000003 6c insb ; l
0000000000000004 6f outsd ; o
0000000000000005 20576f and [edi+0x6f], dl ; <space>Wo
0000000000000008 726c jb 0x76 ; rl
000000000000000a 642024 invalid ; d<space>$
反汇编程序可以做的是使用一些启发式和代码跟踪来决定是否将反汇编的某些部分打印为代码,将其他部分打印为数据。但是反汇编程序永远不能知道代码结束的地方和数据开始的地方,因为在.com
文件中,这种区别仅存在于程序员的头脑中,可能存在于源代码和汇编程序的限制中,但不存在于二进制.com
文件格式本身。