My C code snippet takes the address of the argument and stores it in a memory location (pre-processed code):
void foo(unsigned int x) { *(volatile unsigned int*)(0x4000000 + 0xd4) = (unsigned int)(&x); } int main() { foo(1); while(1); }
I used the SVN version of GCC to compile this code. At the end of the foo function, I would expect the value 1 be stored on the stack, and at 0x40000d4 address pointing to this value. When I compile without optimization using the -O0 flag, I get the expected output of the ARM7TMDI assembly (commented out for your convenience):
.align 2 .global foo .type foo, %function foo: @ Function supports interworking. @ args = 0, pretend = 0, frame = 8 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. sub sp, sp, #8 str r0, [sp, #4] @ 3. Store the argument on the stack mov r3, #67108864 add r3, r3, #212 add r2, sp, #4 @ 4. Address of the stack variable str r2, [r3, #0] @ 5. Store the address at 0x40000d4 add sp, sp, #8 bx lr .size foo, .-foo .align 2 .global main .type main, %function main: @ Function supports interworking. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 stmfd sp!, {r4, lr} mov r0,
It explicitly saves the argument first on the stack and from there saves it to 0x40000d4 . When I compile with optimization using -O1 , I get something unexpected:
.align 2 .global foo .type foo, %function foo: @ Function supports interworking. @ args = 0, pretend = 0, frame = 8 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. sub sp, sp, #8 mov r2, #67108864 add r3, sp, #4 @ 3. Address of *something* on the stack str r3, [r2, #212] @ 4. Store the address at 0x40000d4 add sp, sp, #8 bx lr .size foo, .-foo .align 2 .global main .type main, %function main: @ Function supports interworking. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 stmfd sp!, {r4, lr} mov r0,
This time, the argument is never stored on the stack, even if something from the stack is still stored at 0x40000d4 .
Is this the expected / undefined behavior? Did I do something wrong or did I really find a compiler error and trade?