正确恢复被调用者保存的寄存器
Correctly restoring callee-saved registers
我试图正确理解我在哪里以及如何推送和弹出被调用者保存的寄存器,例如 ebx
onto/off 堆栈以恢复它们供以后使用。
此代码是否正确恢复了 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
returns 时的值与输入时的值相同,因此一切正常。
如果您的程序中有一个调用 print
的 C 函数,那么第一个版本会很糟糕,需要第二个版本。但是在第一个版本中,print
仅从您的 hand-coded main
函数调用,并且您知道 print
会破坏 ebx
而您是采取适当的措施来保存和恢复它,这样就可以了。
换句话说,在第一版代码中,print
不符合标准的C调用约定。但由于您实际上从未从 C 代码中调用它,所以这不一定是个问题。在第二个版本中,它确实符合,这可能在美学上更好,并且维护起来可能不那么混乱。
我试图正确理解我在哪里以及如何推送和弹出被调用者保存的寄存器,例如 ebx
onto/off 堆栈以恢复它们供以后使用。
此代码是否正确恢复了 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
returns 时的值与输入时的值相同,因此一切正常。
如果您的程序中有一个调用 print
的 C 函数,那么第一个版本会很糟糕,需要第二个版本。但是在第一个版本中,print
仅从您的 hand-coded main
函数调用,并且您知道 print
会破坏 ebx
而您是采取适当的措施来保存和恢复它,这样就可以了。
换句话说,在第一版代码中,print
不符合标准的C调用约定。但由于您实际上从未从 C 代码中调用它,所以这不一定是个问题。在第二个版本中,它确实符合,这可能在美学上更好,并且维护起来可能不那么混乱。