主题:请教一个调试的问题
listen2
[专家分:0] 发布于 2007-05-08 21:59:00
这是书本上的一个习题:
源程序如下:codesg segment
start:
mov ax,2000H
mov ss,ax
mov sp,0
add sp,4
pop ax
pop bx
push ax
push bx
pop ax
pop bx
mov ax,4c00H
int 21H
codesg ends
end start
用debug跟踪它的执行过程,到pop ax就无法执行下去了 说是遇到无效指令。请问是为什么?
回复列表 (共1个回复)
沙发
小牛斑斑 [专家分:1210] 发布于 2007-05-09 17:26:00
这个程序是个有问题的程序,它是个逻辑上的程序,不会出现编译问题,但在CPU上执行肯定会出问题。具体解释如下:
mov ax,2000h
mov ss,ax
mov sp,0
程序没有定义堆栈段,而是通过mov ss,ax指令定义了堆栈段的基地址,这种定义堆栈段的方法叫做硬性编码,但到这里还没有暴露出硬性编码的bug,堆栈段在内存中的基地址是20000H。mov sp,0指令把堆栈指针设置到了堆栈顶部,在内存的00000H处,这个区域不是一般的应用程序可以修改的,不能作为堆栈使用,00000h~000FFH是中断向量表的所在地,这个地方从理论上是只读的,并应该随意向这里写东西。但程序执行到这里,既没有读,也没有写内容,仍然没有引爆错误。接下来:
add sp,4
pop ax
pop bx
add sp,4,设置了堆栈指针的位置,没问题,但是设置的不是地方。
pop ax
pop bx
上面两条指令是读取00002H和00000H处的内容,没错的。
push ax
push bx
上面两句修改了中断向量表,中断向量表的0 号(除法错中断)中断都是非常重要的,
注意了,pop ax pop bx和push ax push bx不对应,调换了0000 和0002两个字单元的内容,也就是说错误的写了中断向量表的0号中断的内容,后面在调用int 21中断的时候,可能是CPU或者NTVDM cpu检测到了0号中断向量入口地址被错误的修改了,引发了错误。
解决办法:将
push ax
push bx
改为:
push bx
push ax
就是将读取的数据,原样的写回去,这就没事了。
(转贴)http://www.it130.cn/Article/FAQ/bianchengyuyan/huibian/2007-3-7/2007030721335720.html
我来回复