I’m trying to put some C hooks into some code that someone else wrote in asm. I don’t know much about x86 asm and I want to make sure I’m doing this safely.
So far I’ve got this much:
EXTERN _C_func
CALL _C_func
And that seems to work, but I’m sure that’s dangerous as-is. At the very least it could be destroying EAX, and possibly more.
So I think all I need to know is: Which registers does C destroy and how do I ensure the registers are being saved properly? Is there anything else I can do to make sure I can safely insert hooks into arbitrary locations?
I’m using Visual Studio for the C functions, if that helps.
Thank you.
UPDATE:
I looked up the “paranoid” method several people suggested and it looks like this:
pushfd
pushad
call _C_func
popad
popfd
AD = (A)ll general registers
FD = (F)lags
(I’m not sure what the ‘d’ stands for, but it means 32-bit registers instead of 16-bit.)
But the most efficient method is illustrated in Kragen’s answer below. (Assuming you don’t need the preserve the flags. If you do, add the FD instructions.)
Also, be careful about allocating lots of stack variables in your C function as it could overrun the asm subroutine’s stack space.
I think that about does it, thanks for you help everyone!
If the calling convention is cdecl and the signature of C_funct is simply:
Then that is perfectly “safe”, however the registers EAX, ECX and EDX are “available for use inside the function”, and so may be overwritten.
To protect against this you can save the registers that you care about and restore them afterwards:
By convention the registers EBX, ESI, EDI, and EBP shouldn’t be modified by the callee.
I believe that the flags may be modified by the callee – again if you care about preserving the value of flags then you should save them.
See the Wikipedia page on x86 calling conventions.