Search code examples
cgccarminline-assembly

gcc optimize variable away before systemcall


Using Codesourcery arm-linux-eabi crosscompiler and have problems with the compiler not executing certain code because it thinks it's not used, especially for a systemcall. Is there any way to get around this?

For example this code does not initialize the variable.

unsigned int temp = 42;
asm volatile("mov R1, %0 :: "r" (temp));
asm volatile("swi 1");

In this case temp never get initialized to the value 42. However if I add a printk after the initialization, it gets initialized to the correct value 42. I tried with

unsigned int temp __attribute__ ((used)) = 42;

Still doesn't work but I get a warning message:

'used' attribute ignored [-Wattributes]

this is in the linux kernel code.

Any tips?


Solution

  • This is not the correct way to use inline assembly. As written, the two statements are separate, and there is no reason the compiler has to preserve any register values between the two. You need to either put both assembly instructions in the same inline assembly block, with proper input and output constraints, or you could do something like the following which allows the compiler to be more efficient:

    register unsigned int temp __asm__("r1") = 42;
    __asm__ volatile("swi 1" : : "r"(temp) : "memory");
    

    (Note that I added memory to the clobber list; I'm not sure which syscall you're making, but if the syscall writes to any object in userspace, "memory" needs to be listed in the clobberlist.)