我正在用汇编语言开发一些函数,一开始,我的函数以下列三种方式传递参数:
现在我发现上述三种方式的混合使得事情变得复杂。而且我总是陷入这样的境地,我不得不挠头以确定某些寄存器是否受到污染。所以我决定只通过 stack 传递参数。并使用以下函数模板作为一个懒惰的一劳永逸解决方案:
pushl %ebp
movl %esp, %ebp
pushal <--- save all the registers, this is kind of a lazy solution
subl xxx, %esp <--- allocate space for local variables
....
popal <--- restore all the registers
movl %ebp, %esp
popl %ebp
(addl yyy, %esp)<--- if it is __stdcall convention, the callee will clear the stack
ret
(xxx是局部变量的大小,yyy是调用者推送的参数大小。)
调用者负责推送参数并清除堆栈(如C调用约定)。当然,如果参数的数量是固定的,我可以让被调用者清除堆栈(就像Windows上的__stdcall约定)。
我希望这个模板可以减轻我对寄存器使用的混淆。能实现吗?如果效率低,是否有更好的方法?我想听听你的意见。
非常感谢。
嗨,我的代码有错误,所以我纠正了这个:
pushl %ebp
movl %esp, %ebp
pushal <--- save all the registers, this is kind of a lazy solution
subl xxx, %esp <--- allocate space for local variables
....
addl xxx, %esp <--- reclaim the space for local variables
popal <--- restore all the registers
movl %ebp, %esp
popl %ebp
ret yyy <--- for __stdcall convention, the callee will clear the parameters pushed on stack by caller
答案 0 :(得分:1)
通常,特定平台的ABI将定义calling convention,说明如何处理每个寄存器。一个简单的约定可能是您调用的任何函数都可以废弃eax
,ebx
和edx
,但ecx
,esi
和edi
将由被调用的函数保存。
通过这种方式,你可以在一些寄存器上进行简单的功能步骤,如果需要它们而不必保存它们,但是更复杂的函数可以使用他们想要的所有寄存器,只要它们保存了保存的寄存器。第一