On 01/24/2012 11:35 AM, Konstantin Vladimirov wrote: > > This problem is backend independent, so I build reproduction in x86 > backend. Consider code: > > int func(int x); > > int test(int x, int *data) > { > int retval; > register int *buffer asm ("eax"); > > buffer = data; > retval = func(x); > __asm__ __volatile__ (".internal_label _t." "4096" > ".%0.%1.%2:;nop"::"ri" (buffer), "ri" (4137), "ri" (4)); > return retval; > } > > here nop will be replaced for something, that essentially uses %eax, > but it is not actually required for minimal reproduction. > > being compiled with gcc (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch > revision 160292] > > with following options: > > gcc -m32 -O2 -S -fomit-frame-pointer reprox86.c > > yields assembler: > > .type test, @function > test: > subl $28, %esp > movl 32(%esp), %eax > movl %eax, (%esp) > call func // <--- here eax is clobbered > .internal_label _t.4096.%eax.$4137.$4:;nop 0 > addl $28, %esp > ret > > That looks quite odd. I have a question -- why compiler doesn't save & > restore buffer (i.e. %eax) value around function call, when we > specifically pointed to %eax usage in the inline assembler > instruction? Well, hold on: you've said that you want buffer to live in register EAX for the entire duration of test(). GCC assumes that you know what you are doing, know that EAX is call-clobbered, and are using EAX because you want to pass arguments to func() in EAX. In other words, it's not a bug, it's a feature. This is exactly how register asm variables are used to do system calls in GNU/Linux. If you want to pass a value in EAX to an asm, do this: int test(int x, int *data) { int retval; retval = func(x); __asm__ __volatile__ (".internal_label _t." "4096" ".%0.%1.%2:;nop"::"a" (data), "ri" (4137), "ri" (4)); return retval; } Andrew.