Page 1 of 1

gcc and registers

Posted: Thu Feb 21, 2008 8:58 pm
by dumaisp
Hi,

I have an asm file and a C file that I compile like this:
gcc -m32 -c process.s
gcc -m32 -c mem.c
ld process.o mem.o .........

in process.s I call functions from mem.c.
At home I compile this using GCC4 and when I disassemble mem.o (the one writtin in C), I notice that only the EAX register is being used. That is fine, I rely on that because in process.s I don't want the other registers modified.

But now I compile this using GCC3.4.6 and I noticed that my function uses ECX and EDX without even pushing and poping them and at the end. So the function in process.s cannot assume that the registers it uses will still be correct after calling a function written in C.

Obviously, it is better when it uses several registers instead of memory, but it should push/pop them?

Any one have a solution for this, other than pushing my registers before calling the function? There must be a flag I could set with gcc.

Posted: Thu Feb 21, 2008 9:22 pm
by jerryleecooper
I am no expert on this, but I believe that in C, you can't expect your registers to hold valid data after a function call. So you need to push/pop from the function calling your C function.

Did you try to use gcc 4 ( i didnt know it existed) with optimizations on, -O2, for example?

Posted: Fri Feb 22, 2008 2:22 am
by JamesM
There are several general purpose registers: EAX, EBX, ECX, EDX, ESI and EDI.

Three of these are also called 'scratch registers': EAX, ECX, EDX. These, according to the __cdecl calling convention, are not required to be maintained across a function call. So the caller may never assume these registers to have the same value on return as when called.

Re: gcc and registers

Posted: Fri Feb 22, 2008 2:25 am
by jal
dumaisp wrote:Any one have a solution for this, other than pushing my registers before calling the function? There must be a flag I could set with gcc.
I don't think so. GCC does not assume any registers are being saved accross function calls, except for the obvious ones (ESP and EBP). All general purpose registers (EAX, EBX, ECX, EDX, ESI, EDI) may be trashed. EAX holds the return value if it's a non-void function. If there is a flag, check the GCC manual pages.

EDIT: JamesM already provided a more detailed answer. It seems only EAX, ECX and EDX may be trashed.

JAL

Posted: Fri Feb 22, 2008 7:15 am
by dumaisp
Oh, I found this on another thread:
http://www.asmtrauma.com/Articles.htm

Very good documentation.

I find it odd though, the routine should clean itself up. i.e. save/restore all modified registers and clean the stack after. It's like saying: I'm gonna do the dishes before I eat instead of after i'm done eating.

Posted: Fri Feb 22, 2008 8:21 am
by JamesM
save/restore all modified registers
It does. All except the scratch registers.

Posted: Fri Feb 22, 2008 8:32 am
by Solar
dumaisp wrote:I find it odd though, the routine should clean itself up.
No it shouldn't. The caller knows which registers are still needed and which ones could be trashed, so I'm quite OK with the caller saving what it still needs before calling a function. This is thinking beyond x86, mind you.

Cleaning up the stack done by the callee could become problematic when you think about varargs...