答:这个程序是可以正常返回的。
解析:
这个程序将
mov ax,4c00H
int 21H
放到了start标号的上面,codesg段的开头,也就是这两条指令的起始偏移地址是0.
这段程序的主要指令是
这几条。我说明一下这几条指令的作用。这几天指令的作用看懂了,还有jmp指令的偏移量也明白了,那么这题就迎刃而解。
mov di,offset s
作用: 将s标号的偏移地址存放到di寄存器中
mov si,offset s2
作用: 将s2标号的偏移地址存放到si寄存器中
mov ax,cs:[si]
作用: 将s2标号的指令存放到ax中。
s2标号的指令是 jmp short s1
指令。
mov cs:[di],ax
作用: *将s标号的数据替换成ax寄存器里的数据。也就是将s标号的两个nop指令替换为jmp short s1
指令。
上述这四条指令执行后就相当于下面的程序了
assume cs:codesg
codesg segment
mov ax,4c00H
int 21H
start: mov ax,0
s: jmp short s1 ;将原来两条nop指令替换成 jmp short s1指令
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21H
mov ax,0
s2: jmp short s1
nop
codesg ends
end start
上述这些如果看懂的话,那就往下说,说jmp指令的偏移量。
我们知道jmp指令中给出的是位移量而不是内存地址,这样的好处是利于在内存的浮动装配,意思就是说在内存哪一块地方都可以正常执行。
那么偏移量是怎么计算的呢?
偏移量 = 目标标号的偏移地址 - jmp指令执行后的第一条指令的偏移地址。
这个程序中,
这条指令,jmp 0008,表示跳转到偏移地址为8的地方。
可是机器指令是EB F0,而是给出的F0,这个F0是位移量,这是一个补码,不懂补码的可以去其他地方搜寻答案,这里就不讲述了。
F0也就是-10(十六进制)
F0 = 目标标号的偏移地址 - jmp指令后的第一条指令的偏移地址
F0 = 8 - 18 = -10
好了,回归到本题。
上面说到将s2的指令jmp short s1
指令送到s标号处。那我们看一下这条指令的机器码是多少。
是EB F6,这条指令的位移量是F6,也就是-A(十六进制)
我们执行上面那四条指令,查看s标号的指令是否变了。
s标号的指令成功变为了EB F6了。
CPU执行这条指令后,IP = IP + 2 = A , A + F6 = A + -A = 0,
这个就是jmp指令执行后,下一条指令+位移量,就是要跳转到标号处,
结果就跳转到偏移地址为0的mov ax,4c00H处。
接下来就可以正常结束这个程序了。