21,459
社区成员
发帖
与我相关
我的任务
分享
.model small
.data
dw 8 dup(0)
.code
start:
;添加下面3条语句
mov dl,'a'
mov ah,2
int 21h
mov ax, @data
mov ss,ax
mov sp,16
mov ds,ax
mov ax,0
;mov word ptr ds:[0eh],0017h
call word ptr ds:[0eh]
mov ah,7
int 21h
mov ah,4ch
int 21h
end start
就是在程序最开始的时候输出一个字符'a'
直接运行程序发现输出了两个'a'
这时候问题就很明白了.
老师上课讲过:段内间接转移,格式:CALL OPRD实现的过程是:
但事实来看过程不是这样的,而应该是:
(具体这个TMP是什么寄存器或者内存区域我还没搞清楚。。。)
这样就能解释上面所有的现象了:
直接运行时数据区的16个字节一直为0,ds:[0eh]也是0,第一次call语句的时候直接跳到了程序的开头(CS:0h),输出了第二个‘a’,并且ds:[0eh]被修改成call的下一条语句地址。于是第二次call的时候就正常跳到了call下一条语句。
而Debug的时候,ds:[0ah]到ds:[0fh]处被写入了ip、cs、标志寄存器(按顺序)
所以call语句的时候实际上就跳到了以标志寄存器数值为地址的语句去了,ip就飞了
(但是这个地方,执行完call之后的ip并不完全等于ds:[0eh],这个我还没搞懂。)
0 1 2 3 4 5 6 7 8 9 A B C D E F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -- 原始
调用call后:
0 1 2 3 4 5 6 7 8 9 A B C D E F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 0e 00 -- 假设mov ax, 4c00的地址是000e
但debug会把标志、cs、ip也入栈,栈顶就不是000e那个了,所以call的就是别地了,直接执行没这问题