首先将程序编译连接,然后debug调试跟踪。
查看一下寄存器内容
发现IP的初始值为5,说明代码段前面还有其他内容(start前面的两条程序结束指令)。然后查看一下各个指令所占的内存空间
结合这个结果,对两个offset进行分析(不实际计算offset的值也不影响分析这个程序的结果)
其中 mov ax,cs:[si]
指令将 s2 标记处的第一条指令 jmp short s1
复制到 AX 中,并通过下一条指令 mov cs:[di],ax
将 AX 中内容即 s2 标记处的第一条指令 jmp short s1
复制到 s 标记处的前两个字节中,即覆盖了原有的两个 nop 指令。
可以暂时简单理解为程序代码发生了如下变化(实际有些区别,后面再说):
接下来逐步执行
两个占位指令 nop,起到占位作用。继续执行
从这里也能看到,两条 offset 指令以及随后的两条 mov 指令的目的是将后面 s2 标记处的指令复制到标记 s 处。继续执行。
可见执行完 jmp short s
后,下一条指令按照前面的分析来说,应该是执行 jmp short s1
,可为什么程序显示的下一条指令为 jmp 0000
,不是跳转到 s1 标记的地址处执行呢?
根据我们前面学习的知识,我们知道像 jmp short、jmp near ptr、jcxz、loop 等短转移指令,它们在执行时对 IP 的修改是根据转移目的地址和转移起始地址之间的位移来进行的。所以本程序中在 s2 标志处的 jmp 指令,它的作用就是把 IP 往回修改 8 个单位(-8,因为 s1 和 s2 之间的位移是 8)以便可以跳转到 s1 执行。所以将这条指令对应的机器码复制到 s 标记处时,执行时仍是将 IP 往回修改 8 个单位(-8),这样就会跳转到代码段最开始定义的两条程序结束语句,然后结束程序。