Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the x86_64 call instruction on a 64bit system

I'm exploring some disassembled C programs with godbolt and I am having trouble wrapping my head around the x86_64 "call" instruction.

With the C code:

int func(int i)
{
    return i + 1;
}

int main(void)
{
    int i = 5;
    i = func(i);
    return 0;
}

I get the equivalent assembly code:

func:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     eax, DWORD PTR [rbp-4]
        add     eax, 1
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 5
        mov     eax, DWORD PTR [rbp-4]
        mov     edi, eax
        call    func
        mov     DWORD PTR [rbp-4], eax
        mov     eax, 0
        leave
        ret

I have read that when I do call func the return address is pushed onto the stack. Because this is 64 bit assembly I would assume that this address would be 64 bits wide (i.e 8 bytes). However when investigating the assembly for func the line mov DWORD PTR [rbp-4], edi seems to imply that there are only 4 bytes for the return address as [rbp-4] would be 4 bytes past the base pointer of the stack frame. I have a feeling I am fundamentally misunderstanding what is going on here and I was hoping to get some guidance.

I expected mov DWORD PTR [rbp-8], edi but was given mov DWORD PTR [rbp-4], edi

like image 921
BatterySoda Avatar asked Dec 01 '25 18:12

BatterySoda


1 Answers

However when investigating the assembly for func the line mov DWORD PTR [rbp-4], edi seems to imply that there are only 4 bytes for the return address as [rbp-4] would be 4 bytes past the base pointer of the stack frame.

No. That mov instruction has nothing to do with the return address. It is about argument passing. In particular, it copies the value passed to parameter i into the func's stack frame.

I have a feeling I am fundamentally misunderstanding what is going on here and I was hoping to get some guidance.

Yes. The call instruction pushes the return address onto the stack, including updating the stack pointer. When func executes mov rbp, rsp, that sets its frame pointer past the return address, regardless of the size of that address (and also past the stored value of the caller's frame pointer, which func pushed on top). After that, [rbp-4] is the address of the first 4-byte word in func's stack frame.

like image 77
John Bollinger Avatar answered Dec 04 '25 09:12

John Bollinger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!