Assembly language function template. - A simple lazy convention?
I am developing some functions in assembly language, at the beginning, my functions passing the parameters in the following 3 manners:
- registers
- global data in .data section
- through stack
Now I found that the mix of the above 3 manners is making things complicated. And I always fall into the situation where I have to scratch my head to make sure whether certain register is polluted. So I decide to pass the parameters only through stack. And use the following function template as a lazy once-for-all solution:
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, %e开发者_高级运维sp)<--- if it is __stdcall convention, the callee will clear the stack
ret
(xxx is the size of local variables, yyy is the size of paramters pushed by caller.)
The caller is responsible for push parameters and clear the stack (like the C call convention). Of course, if the number of parameters is fixed, I can make the callee to clear the stack (like the __stdcall convention on Windows).
I am hoping this template could relieve me from the confusions of registers usage. Could it achieve that? If it is low efficiency, is there some better approach? I'd like to hear your comment.
Many thanks.
Update 1
Hi again, my code has bugs, so I corrected it like this:
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
Usually the ABI for a particular platform will define a calling convention that states what to do with each register. A simple convention might be that any function you call can trash eax
, ebx
, and edx
, but ecx
, esi
, and edi
will be preserved by the called function.
This way you can have a tradeoff, of having simple function step on a few registers if they need to without having to save them, but more complex functions can use all the registers they want, as long as they save the preserved ones first.
精彩评论