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.
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?
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.
As you probably know, you're free to do what you want with EAX, ECX and EDX, but you'll need to save 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?
Yes, this is usually how it's done. PUSH everything at the start, POP before returning.
But sometimes it may make sense to use a caller-saved register instead. Let's say that you never use EDX in your function, and you don't call any function in a way that could touch it's content. But you want to use EDI in your function. You could save EDI on the stack, or you could save it in EDX.
mov edx, edi
; Do something with EDI without corrupting EDX, e.g. string manipulation
mov edi, edx
instead of
push edi
; Do something with EDI, e.g. string manipulation
pop edi
Using registers is slightly faster than using the stack, so this may give some visible performance improvements if for example you use this function in a loop.
Note that you don't have to save everything at the very start and restore it just before returning. You can save a register right before you use it and restore it as soon as you're done with it, in the middle of a function.