Assembly CALL和RET指令
80x86提供了两条使用堆栈的指令来使子程序调用变得快速而简单。CALL指令执行一个跳到子程序的无条件跳转,同时将下一条指令的地址推入栈中。RET指令弹出一个地址并跳转到这个地址去执行。使用这些指令的时候,正确处理堆栈以便RET指令能弹出正确的数值是非常重要的!
mov ebx, input1
同时把子程序get int改成:
get_int:
call read_int
mov [ebx], eax
ret
前面的例子可以使用这些新的指令来重写。把25行到34行改成:
mov ebx, input1
call get_int
mov ebx, input2
call get_int
同时把子程序get int改成:
get_int:
call read_int
mov [ebx], eax
ret
CALL和RET指令有几个优点:
1、它们很简单!
2、它们使子程序嵌套变得简单。注意:子程序get_int调用了read_int。这个调用将另一个地址压入到堆栈中了。在read_int代码的末尾是一条弹出返回地址的RET指令,通过执行指令重新回到get int代码中去执行。然后,当get int的RET指令被执行时,它弹出跳回到asm main的返回地址。这个之所以能正确运行,是因此堆栈的LIFO特性。
记住弹出压入到堆栈的所有数据是非常重要的。例如,考虑下面的代码:
1 get_int:
2 call read_int
3 mov [ebx], eax
4 ret ; 弹出EAX的值,没有返回地址!!
这个代码将不会正确返回!