子程序在其任务完成后,执行的最后一条汇编指令是RET。根据对该子程序的调用是段内调用还是段间调用,其要实现的操作是不相同的。如果是段内调用,那么RET指令的功能只是把存放在堆栈里的返回地址送IP寄存器;如果是段间调用,那么RET指令的功能就是要把存放在堆栈里的返回地址和段地址,分别送IP寄存器和CS寄存器。因此,RET指令的使用也有多种形式:段内返回、段内带立即数返回、段间返回和段间带立即数返回。下面对它们一一加以介绍。
(1)段内返回格式:RET
执行的操作:IP←(SP+1)(SP)
SP←SP+2
即将当前栈顶元素内容(就是断点的地址)送寄存器IP,然后往栈底方向调整堆栈指针,达到栈顶元素出栈的目的。
(2)段内带立即数返回格式:RET n(或RET <表达式>)
立即数n通常是正偶数。如果汇编格式指令中的n或表达式计算出的值是奇数,汇编时会自动变成n+1。
执行的操作:IP←(SP+1)(SP)
SP←SP+2
SP←SP+n
(3)段间返回格式:RET
执行的操作:IP←(SP+1)(SP)
SP←SP+2
CS←(SP+1)(SP)
SP←SP+2
(4)段间带立即数返回格式:RET n
执行的操作:IP←(SP+1)(SP),SP←SP+2
CS←(SP+1)(SP),SP←SP+2
SP←SP+n
段内返回和段间返回指令的汇编指令格式都是RET,但是汇编后产生的机器代码指令却是不同的。当子程序的属性是NEAR时,对应于段内返回RET指令的机器代码是C3H,对应于段内带立即数返回RET指令的机器代码是C2H;当子程序的属性是FAR时,对应于段间返回RET指令的机器代码是CBH,对应于段间带立即数返回RET指令的机器代码是CAH。所以,定义一个子程序为段间调用时,其类型属性FAR是绝对不能省略的,否则就不能正确实现返回。属性是FAR的子程序也可以被同一代码段的主程序调用。这时,CALL指令虽然与子程序同在一个代码段中,但它执行的却是段间调用操作。由此也表明,CALL指令的属性是由过程的属性决定的。
阅读(14893) | 评论(0) | 转发(0) |