cdecl register preservation

Programming, for all ages and all languages.
Post Reply
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

cdecl register preservation

Post by evoex »

Hello all,

I read somewhere that for an cdecl call the registers eax, ecx and edx do not need to be preserved by the called function. However, when testing the following code on gcc:

Code: Select all

#include <stdio.h>

void __attribute__((cdecl)) test()
{
	__asm__("movl $0, %eax");
}

int __attribute__((cdecl)) test1()
{
	int a;
	scanf("%d", &a);
	return a;
}

int main()
{
	int a = test1();
	test();
	printf("%d\n", a);
}
And optimizing with -O2, the printf would always show 0, probably meaning that eax DOES need to be preserved for void functions. Is this correct?
What about the other registers? They are not preserved, is that correct?

What about the syscall calling convention? Is the same true, there?

Also, how do I specify the calling convention to use in gcc? The above actually complains about it being ignored - but I believe cdecl is the default in gcc anyway (otherwise my complaint is even wrong). So how would I specify the syscall calling convention, for instance?
Edit: never mind this last question, I was accidentally compiling it on 64 bits, which is why cdecl was ignored. But the issue with eax was not fixed compiling it as 32 bits.

Thanks in advance
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: cdecl register preservation

Post by gerryg400 »

The problem is probably that your inline asm

Code: Select all

 __asm__("movl $0, %eax");
is trashing the EAX register but GCC doesn't know. I'm guessing that if you put the proper constraints on that line of asm your problem will go away.
If a trainstation is where trains stop, what is a workstation ?
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: cdecl register preservation

Post by evoex »

gerryg400 wrote:The problem is probably that your inline asm

Code: Select all

 __asm__("movl $0, %eax");
is trashing the EAX register but GCC doesn't know. I'm guessing that if you put the proper constraints on that line of asm your problem will go away.
Ahh okay that makes sense. So basically I can safely change eax even in a void function, without having to worry about extremely complex bugs in the future? ;-)

Thanks for your answer!
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: cdecl register preservation

Post by gerryg400 »

evoex wrote:... So basically I can safely change eax even in a void function, without having to worry about extremely complex bugs in the future? ;-)
No. The future is full of complex bugs.
If a trainstation is where trains stop, what is a workstation ?
User avatar
Tobba
Posts: 21
Joined: Fri Mar 18, 2011 3:24 pm

Re: cdecl register preservation

Post by Tobba »

What happens without -O2? GCC most likely tries to optimize the code, but doesnt know you're trashing the register, which makes it think eax is not trashed within the function and can be preserved until the printf call?
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: cdecl register preservation

Post by JamesM »

Tobba wrote:What happens without -O2? GCC most likely tries to optimize the code, but doesnt know you're trashing the register, which makes it think eax is not trashed within the function and can be preserved until the printf call?
Hi,

I'd be highly surprised if the "test" function isn't being inlined. When it's out of line (needs to be CALLed), the compiler assumes that eax will be trashed (along with other caller save regs as per the ABI).

With -O2, it's likely test() has been inlined, so the compiler no longer has to adhere to the ABI and EAX gets corrupted. As a previous poster has said, changing the inline assembly statement so that the eax constraint is known will alleviate this:

Code: Select all

int dummy;
asm volatile("movl $0, %0" : "=a" (dummy));
Or just compile with -fno-inline.
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: cdecl register preservation

Post by evoex »

Yeah; the C code wasn't actually part of any production code or so, it was only to test whether the EAX register could be changed or not. Because wikipedia said it couldn't (I already changed that), where other sources said it could. So I made this test and wondered about the results - but it is understandable GCC inlines it, causing this "bug".
So I'm not worried about it anymore, thanks for your help guys!
Post Reply