Why does GCC -O0 usually store the first local variable at [ebp-4], and why not always?

Viewed 106

I am currently learning reverse engineering using the x86 Instruction Set and had the general understanding that the first local variable of a function is always stored at the address [ebp-4]. However, the following C function doesn't seem to follow that principle and I'm struggling to find out why:

int check_authentication(char *password) {
    int auth_flag = 0;
    char buffer[16];
    strcpy(buffer, password);
    if(strcmp(buffer, "password") == 0)
        auth_flag = 1;
    return auth_flag; 
}

For the line int auth_flag = 0, I was expecting the corresponding x86 ASM translation to be mov DWORD PTR[ebp-4], 0. However, the first lines of the compiled ASM output of the above function look like below (compiled via gcc -m32 -O0 [...]):

check_authentication:
        push    ebp
        mov     ebp, esp
        sub     esp, 40
        mov     DWORD PTR [ebp-12], 0 ; <- Why ??

Why does it use the memory address [ebp-12] and not [ebp-4]?
I figured this is related to function calls within the function (i.e., if I remove the calls to strcpy and strcmp, then [ebp-4] is used as expected).
I cannot seem to figure out why this is happening in the first place though.

1 Answers

C is not a high-order assembly. You cannot expect the compiler to compile C to assembly statement by statement.

Is the first local variable in x86 ASM always stored at location [ebp-4]?

No, that would tie the hands of the C compiler authors too much.

Related