创建 cdecl 函数时如何保存寄存器的状态?

How to preserve the state of the registers when creating a cdecl function?

我正在编写一个使用 cdecl 调用约定的函数,因此我需要确保寄存器的状态保留为调用该函数之前的状态。

我的问题是这通常是如何执行的。是否只是在函数开始时将寄存器压入堆栈,然后在函数结束时将它们弹出到寄存器中?

I am writing a function that uses the cdecl calling convention, and so I need to make sure that the state of the registers is preserved as they were before calling the function.

您可能知道,您可以自由地使用 EAX、ECX 和 EDX 做任何您想做的事情,但是您需要保存 pretty much everything else

My question is how this is usually performed. Is it just a matter of pushing the registers on the stack on the start of the function and then popping them out into the registers at the end of the function?

是的,通常都是这样做的。开始时 PUSH 一切,返回前 POP。

但有时使用调用者保存的寄存器可能更有意义。 假设您从不在您的函数中使用 EDX,并且您不会以可能触及它的内容的方式调用任何函数。但是您想在您的函数中使用 EDI。您可以将 EDI 保存在堆栈中,也可以将其保存在 EDX 中。

mov edx, edi
; Do something with EDI without corrupting EDX, e.g. string manipulation
mov edi, edx

而不是

push edi
; Do something with EDI, e.g. string manipulation
pop edi

使用寄存器比使用堆栈稍微快一些,因此如果您在循环中使用此函数,这可能会带来一些明显的性能改进。

请注意,您不需要在一开始就保存所有内容并在返回之前将其恢复。 您可以在使用前立即保存寄存器,并在使用完后立即在函数执行过程中将其恢复。