Allocating variables on the stack in x86 assembly. rbp and rsp vs esp and ebp
Asked Answered
O

1

11

I have recently been learning assembly, and decided to disassemble some of my own executables to study from. I've noticed online resources often reference esp and ebp, the stack and base pointer. I wrote this program:

int comp(int a, int b) {
    return a == b;
}
int main() {
    int a = 1;
    int b = 2;
    comp(a, b); 
}

And in Radare 2 this disassembles into:

0x0040050e    55           push rbp
|           0x0040050f    4889e5       mov rbp, rsp
|           0x00400512    4883ec10     sub rsp, 0x10
|           0x00400516    c745f801000. mov dword [rbp-0x8], 0x1
|           0x0040051d    c745fc02000. mov dword [rbp-0x4], 0x2
|           0x00400524    8b55fc       mov edx, [rbp-0x4]
|           0x00400527    8b45f8       mov eax, [rbp-0x8]
|           0x0040052a    89d6         mov esi, edx
|           0x0040052c    89c7         mov edi, eax
|           0x0040052e    e8c3ffffff   call sym.comp
|              sym.comp(unk)
|           0x00400533    b800000000   mov eax, 0x0
|           0x00400538    c9           leave
\           0x00400539    c3           ret

Why is it using rbp and rsp? Is this just the way my compiler likes to do things? Also, why is it rbp-value to create space on the stack, shouldn't it be rbp+value to allocate more space?

Overwork answered 27/2, 2017 at 15:3 Comment(7)
It's just 32-bit (esp,ebp) vs. 64-bit (rsp,rbp)Brunn
Can you explain why its the base pointer - a value instead of addition? I thought ebp was the bottom of the stack.Overwork
I don't understand what you mean, but ebp/rbp (usually) marks the beginning (top-address) of the new stack frame for the current function.Brunn
So I think what Im trying to say is this. esp \n buffer\n ebp and ebp is in higher memory and the bottom of the stack, or is it the top?Overwork
Since this stack grows from high addresses to low addresses it is a matter of opinion ;)Brunn
rbp+value are function arguments, when stack was used (not in 64b ABI, arguments for sym.comp are in edi and esi, not in stack). rbp-value are local variables (allocated by sub rsp,<bytes_to_allocate>) ... [rbp+0] = old rbp and [rbp+8] is return address.Cobalt
If you compile without optimizations turned on, the compiler often generates stupid code. What did you expect?Pyroligneous
H
23

You are compiling for 64-bit, so rbp and rsp are just the 64-bit equivalents to the 32-bit ebp and esp variables. Even in 64-bit code you often see the 32-bit (e**) registers used when possible - but you won't see that with rsp or rbp usually1 since they hold pointers that almost always need to be 64-bit.

Since rbp points to the the base of your stack frame (i.e., the top of the stack on function entry) and stacks on x86 grow downwards (towards lower addresses), the local arguments will be accessed at negative addresses relative to rbp.


1 You might occasionally see ebp used in 64-bit code, but that's just because the compiler has relieved it from its usual frame-pointer duties and is just using it as another GP register.

Hankering answered 27/2, 2017 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.