王爽 汇编语言 检测点 10.5 (1)

在学习王爽《汇编语言(第3版)》 检测点 10.5 (1)时,按章节前面的理论知识推理,下面这段汇编代码执行后程序返回前ax的值应该为3!但将这段汇编代码编译链接成可执行文件,并使用Debug.exe加载后,通过-t命令单步执行时,死活都得不到预期的结果,死磕了半天终于知道原因(没办法,还没学到后面的中断!),下面把实验过程记录一下,避免后来者遇到同样的问题困扰,先把汇编源代码贴上来:

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.exe工具装载,效果如下:

然后我通过-t命单步执行,并不时查看栈段(SS)和数据段(DS)中的数据变化,效果如下:

结果发现MOV SS,AX后(Debug.exe会自动执行后面的MOV SP,0010,即源程序中的mov sp,16),目标栈内的数据并没有像下面这段源程序装载并初始化时指定的全为0的值:

stack segment dw 8 dup (0) stack ends

而是在栈内压入了3个字的数据,后经观察和资料收集得出这3个字中的数据是用于调试中断时记录现场的,其中就包括中断时的CS和IP值(由于学到这章时还没有学后面的关于中断的知识,所以在这里耗了点时间);

继续-t单步执行下去,效果如下:

现在栈段SS和数据段DS指向了相同的内存区,里面的数据当然也一样!继续向下-t单步执行

结果发现CALL命令中目标内存DS:000E单元中的值不再是我们所预想的、程序初始化时的值0000~~~

这个时候继续向下-t单步执行下去,程序就不知道跑到哪里去了(其实就是跑到CS:0192后面去了)

上面我们已经知道了DS:000E内存单元和SS:000E内存单元其实都指向了相同的内存单元,而SS:000E内存单元的值由于调试,将调试中断的现场数据保存到了该内存单元中,进而影响了“CALL [000E]”命令,因为DS:000E中的值不是所期望的值了,最终导致程序不能按理论预期得到结果!(这个时候你可能像我一样无法理解:我明明没有调试、没有中断啊???)

其实这就是对Debug.exe工具不够了解的原因,Debug.exe的-t命令每一次都是在调试,该命令每一次也都会中断(停住嘛)!

这就导致了使用Debug.exe工具的-t单步执行该程序,你肿么都没办法得到预期的效果,那怎么办呢?直接双击执行又看不到效果~~

其实我们还可以用Debug.exe工具的-g命令,该命令可以直接运行到指定的IP处,中途不产生调式中断(到达目标IP处时才中断)!中样就不会影响执行“CALL [000E]”命令时DS:000E内存中的值了!效果如下:

执行到指定IP后,我们再来查看AX中的值,发现结果符合预期了,AX=3

经验分享 程序员 微信小程序 职场和发展