codecamp

Assembly CALL和RET指令

80x86提供了两条使用堆栈的指令来使子程序调用变得快速而简单。CALL指令执行一个跳到子程序的无条件跳转,同时将下一条指令的地址推入栈中。RET指令弹出一个地址并跳转到这个地址去执行。使用这些指令的时候,正确处理堆栈以便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指令


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的值,没有返回地址!!

这个代码将不会正确返回!



Assembly 间接寻址及堆栈
Assembly 调用约定
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }