程序可以正常返回:
- mov ax, cs:[si] 和 mov cs:[di], ax 两条指令将标号 s2 处的指令(好吧,实际上程序运行的时候指令已经被编译器转换成偏移形式的字节码了)复制到了 s 处,该字节码正好是两个字节,刚好放置在两个 nop 符处
- 使用 debug 运行程序,我们发现 jmp short s1 对应的字节码是 EBF6,这是补码形式表示的,二进制表示是 1111 0110, 负数的补码是除符号位按位取反,然后加 1, 结果是 1000 1010, 即 -10, 回跳 10 个字节,即从 jmp short s1 (s1 标号处)的下一个字节的偏移地址 a (注释右边部分是在本人机器上的偏移地址) 处,回跳 10 个字节之后,执行偏移地址 0 处的代码,程序可以正常返回。
assume cs:codesg
codesg segment ; 偏移地址:
mov ax, 4c00h ; 0
int 21h ; 3
start: mov ax, 0 ; 5
s: nop ; jmp short s1 ; 8
nop ; 9
mov di, offset s ; a
mov si, offset s2 ; d
mov ax, cs:[si] ; jmp short s1 ; 11
mov cs:[di], ax ; 14
s0: jmp short s ; 16
s1: mov ax, 0 ; 18
int 21h ; 1B
mov ax, 0 ; 1D
s2: jmp short s1 ; 20
nop ; 22
codesg ends
end start