正确还原被调用方保存的寄存器

问题描述

我试图正确地理解将ebx之类的被调用者保存的寄存器压入/弹出堆栈的位置和方式,以恢复它们以供以后使用。

此代码是否正确恢复了ebx寄存器?

global main
extern printf

section .text:

print:
    mov     eax,0x1
    add     eax,ebx

    push    eax
    push    message
    call    printf
    add     esp,8
    ret

main:
    mov     ebx,0x1
    push    ebx
    call    print
    pop     ebx
    ret

message db "result = %d",10,0       

使用后是否应立即弹出ebx

global main
extern printf

section .text:

print:
    push    ebx
    mov     ebx,0x1
    mov     eax,8
    pop     ebx
    ret
main:
    call print
    ret

message db "result = %d",0       

解决方法

两种方法都可以,但是第二种则比较传统。

规则是这样的:当编译器生成代码以调用函数时,它假定ebx的内容在调用后与以前相同。在您的程序中,唯一适用的情况是调用main的启动代码。对于您的两个版本的代码,ebx返回时main的值与输入时相同,因此一切正常。

如果您的程序中有一个名为print的C函数,则第一个版本将是错误的,而第二个版本将是必需的。但是,正如第一个版本中的情况一样,print仅从您的手动编码main函数中调用,并且您知道print会破坏ebx,并且您采取了适当的措施保存和还原它的操作,就可以了。

换句话说,在代码的第一个版本中,print不符合标准的C调用约定。但是,由于您从未真正从C代码调用过它,所以这不一定是问题。在第二个版本中,它确实符合要求,从美学上讲可能更好,而且维护起来也不太混乱。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...