2

I compiled the following program using gcc version 4.6.3 on Ubuntu 32bit with the command gcc -ggdb -o test test.c


void test(int a, int b, int c, int d)
{
    int flag;
    char buffer[10];
flag = 31337; buffer[0] = 'a'; a = 5; } int main(void) { test(1, 2, 3, 4); return 0; }

The disassembly of the above test function in gdb is :-


   0x08048404 <+0>:     push   ebp
   0x08048405 <+1>:     mov    ebp,esp
   0x08048407 <+3>:     sub    esp,0x28
   0x0804840a <+6>:     mov    eax,gs:0x14
   0x08048410 <+12>:    mov    DWORD PTR [ebp-0xc],eax
   0x08048413 <+15>:    xor    eax,eax
   0x08048415 <+17>:    mov    DWORD PTR [ebp-0x20],0x7a69
   0x0804841c <+24>:    mov    BYTE PTR [ebp-0x16],0x41
=> 0x08048420 <+28>:    mov    DWORD PTR [ebp-0x1c],0x5
   0x08048427 <+35>:    mov    eax,DWORD PTR [ebp-0xc]
   0x0804842a <+38>:    xor    eax,DWORD PTR gs:0x14
   0x08048431 <+45>:    je     0x8048438 
   0x08048433 <+47>:    call   0x8048320 <__stack_chk_fail@plt>
   0x08048438 <+52>:    leave
   0x08048439 <+53>:    ret

As much as I know, the assembly instruction after arrow corresponds to the C instruction a = 5; in test function. So the address [ebp-0x1c] should represent the address of variable a.
But the address that [ebp-0x1c] represents is 0xbffff2bc and the address of variable a is 0xbffff2e0.
I don't understand how both addresses can be different. Is this some kind of optimization done by gcc?

3

Since you're not reading a anywhere, it seems gcc doesn't even bother reading it from the stack, and creates a local variable for it. Try replacing the a=5 with a+=5, so the compiler has to read the variable, and the instruction will probably be changed to access [ebp+8], which is where the parameter should be stored.

The reason for this behaviour might be that gcc tries to make the 32 bit code generation more similar to the 64 bit version, where parameters are passed in registers, and need to be saved below the stack pointer if the compiler needs the register, or a pointer to the parameter needs to be created. Doing the same in 32 bit - at least sometimes - might help the developers share code between the 32- and 64 bit optimizers.

2
  • Yep specifically, if it's accessing the argument it should be [ebp + 8]. ebp is BFFFF2D8 so if you add 8 to that, we get the value of 0xbffff2e0 the op expected. – broadway Jul 11 '14 at 21:21
  • Replacing the a=5 with a+=5 did store 5 at the address of a. Although its useless to accept an argument which is to be modified without even reading from it once. But why is it creating a new variable and not using the one passed. One answer might be what you suggested that it is trying to generate 32 bit code more similar to 64 bit version. – rht Jul 12 '14 at 14:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.