assume cs:code
stack segment
dw 8 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ds,ax
mov ax,0
call word ptr ds:[0EH]
inc ax
inc ax
inc ax
mov ax,4c00h
int 21h
code ends
end start
我用debug执行上面的代码,到call指令之前我看了一下ss:0e到0f之间的数据为77,0e。当call执行完了ss:0e到0f之间的数据变为11,00没错,但是现在call指令push ip后,ip的数据再会改为ds:[0EH]内存处的数据,因为ds==ss,所以ds:[0EH]即为ss:[0EH],但是ss:[0EH]处的数据为77,0e, 但是我d查看内存ip为什么是3302,而不是0e77或者是0011呢?
请高手们多多指点,谢谢了!
------解决方案--------------------
这个代码不是这么看的,更不能用 debug 来单步什么的,而应该是单纯的静态分析,主要是针对堆栈的作用来的。如果用 debug 单步什么的话,会给堆栈写入内容导致 call 去了错误的地方,失去了这个代码设计的本来意义。
call word ptr ds:[0EH],正常运行时 ds:[0Eh] 应该是 00 00 吧,所以其实这个 call 应该是转移到 start: 处,并将返回地址及其下一指令地址压栈在 ds:[0Eh] 处;当程序再次有 start: 运行到这个 call 指令时,由于 ds:[0Eh] 处为其后的 inc ax 指令的地址,所以会跳到这个 inc ax 指令接着向下运行,并再次将返回地址压栈到 ds:[0Ch] 处(尽管已经没有意义了);这么运行到最后的程序结束返回 DOS,压栈的两个返回地址也无用武之地。
窃以为,这样的题目设计,有点儿小聪明,但也仅仅是小聪明,并不怎么适合初期的,没有必要在这上面耽搁多少的时间。