Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 正确还原被调用方保存的寄存器_Assembly_Scope_X86_Cpu Registers_Calling Convention - Fatal编程技术网

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

Assembly 正确还原被调用方保存的寄存器,assembly,scope,x86,cpu-registers,calling-convention,Assembly,Scope,X86,Cpu Registers,Calling Convention,我试图正确理解我在哪里以及如何将被调用方保存的寄存器(如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

我试图正确理解我在哪里以及如何将被调用方保存的寄存器(如
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, 0x1
    add     eax, ebx

    push    eax
    push    message
    call    printf
    add     esp, 8
    pop     ebx
    ret
main:
    call print
    ret

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

两种方法都可以,但第二种方法更为传统

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

如果您的程序中有一个名为
print
的C函数,那么第一个版本就不好,需要第二个版本。但是在第一个版本中,
print
仅从手动编码的
main
函数调用,您知道
print
将关闭
ebx
,并且您正在采取适当的操作来保存和恢复它,所以这很好


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

两种方法都可以,但第二种方法更为传统

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

如果您的程序中有一个名为
print
的C函数,那么第一个版本就不好,需要第二个版本。但是在第一个版本中,
print
仅从手动编码的
main
函数调用,您知道
print
将关闭
ebx
,并且您正在采取适当的操作来保存和恢复它,所以这很好


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

如果以类似的方式使用,在汇编中还需要
push
ed和
pop
ped哪些寄存器?只要
eax
ebx
?@kdi_342:任何保留调用的寄存器都应被视为相同的。对于32位x86调用约定,这是除EAX、ECX和EDX之外的所有整数reg。另请参见第一种方法实际上并不好:main在保存/恢复EBX之前写入EBX,这完全没有意义@kdi_342,您已经销毁了调用方的值,如果
print
遵循ABI,则
call print
将保留该值。但它并没有遵循标准的调用约定:它显然是在使用EBX将arg传递给
print
?整个事情非常奇怪,因为任何地方都没有
ret
指令,所以两个版本都会循环,直到溢出堆栈并崩溃。@Nate:你在考虑AT&T语法吗
addeax,ebx
读取ebx而不写入,因此第一个版本的
print
不会对ebx造成冲击。但它确实读过。我不知道该怎么说这个代码,因为它太奇怪了,但是你的答案似乎与代码不一致。是的,你是对的,我没有仔细阅读。当我有更多时间时将尝试修复。如果以类似的方式使用,在汇编中还需要对哪些寄存器进行
push
ed和
pop
ped?只要
eax
ebx
?@kdi_342:任何保留调用的寄存器都应被视为相同的。对于32位x86调用约定,这是除EAX、ECX和EDX之外的所有整数reg。另请参见第一种方法实际上并不好:main在保存/恢复EBX之前写入EBX,这完全没有意义@kdi_342,您已经销毁了调用方的值,如果
print
遵循ABI,则
call print
将保留该值。但它并没有遵循标准的调用约定:它显然是在使用EBX将arg传递给
print
?整个事情非常奇怪,因为任何地方都没有
ret
指令,所以两个版本都会循环,直到溢出堆栈并崩溃。@Nate:你在考虑AT&T语法吗
addeax,ebx
读取ebx而不写入,因此第一个版本的
print
不会对ebx造成冲击。但它确实读过。我不知道该怎么说这个代码,因为它太奇怪了,但是你的答案似乎与代码不一致。是的,你是对的,我没有仔细阅读。当我有更多的时间时,我会设法解决的。