回 帖 发 新 帖 刷新版面

主题:请教一个调试的问题

这是书本上的一个习题:
源程序如下: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个回复)

沙发

这个程序是个有问题的程序,它是个逻辑上的程序,不会出现编译问题,但在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

我来回复

您尚未登录,请登录后再回复。点此登录或注册