4

Consider the following program, compiled using x86-64 GCC 12.2 with flags --std=c++17 -O0:

int square(int num, int num2) {
    int foo = 37;
    return num * num;
}

int main () {
    return square(10, 5);
}

The resulting assembly using godbolt is:

square(int, int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-20], edi
        mov     DWORD PTR [rbp-24], esi
        mov     DWORD PTR [rbp-4], 37
        mov     eax, DWORD PTR [rbp-20]
        imul    eax, eax
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        mov     esi, 5
        mov     edi, 10
        call    square(int, int)
        nop
        pop     rbp
        ret

I read about shadow spaces and it appears that in x64 there must be at minimum 32 bytes allocated: "32 bytes above the return address which the called function owns" ...

With that said, how is the offset -20 determined for the parameter num? If there's 32 bytes from rbp, wouldn't that be -24?

I noticed even if you add more local variables, it'll remain -20 until it gets pushed over to -36, but I cannot understand why. Thanks!

phuclv
  • 37,963
  • 15
  • 156
  • 475
MathBunny
  • 896
  • 1
  • 8
  • 16
  • I will reopen if the dup is wrong (but I don't think it is). – Paul Sanders Feb 17 '23 at 12:52
  • The duplicate was helpful, but I'm still not sure why it's precisely `-20` - the 32 bytes makes sense for the four registers but still cannot explain how it's computed – MathBunny Feb 17 '23 at 13:09
  • 2
    0x20 = 32. You want to reserve space for four 8-byte registers. – Botje Feb 17 '23 at 13:26
  • 1
    @Botje • Wouldn't that be `20h` or `0x20` or (AT&T style) `$0x20`? (I'm not well versed in Intel assembly. 6502 and 68000 were the one's I've used extensively.) – Eljay Feb 17 '23 at 13:53
  • 3
    @PaulSanders gcc on Godbolt compiles code for Linux, so there isn't any shadow space at all. Only if you use MSVC then there'll be some instructions for adjusting the shadow space – phuclv Feb 17 '23 at 17:00
  • 2
    @Botje the value above is 20, not 0x20. The duplicate is wrong and what the OP said about shadow spaces isn't relevant here as this isn't Windows assembly – phuclv Feb 17 '23 at 17:21
  • @phuclv OK, reopened. – Paul Sanders Feb 17 '23 at 17:46
  • Looks like it's a non-optimised build. What happens if you enable optimisation? – Paul Sanders Feb 17 '23 at 17:48
  • 3
    @PaulSanders: An optimized build won't use memory at all, of course, just registers unless you make some of the variables `volatile`. Perhaps related to [Why does GCC allocate more space than necessary on the stack, beyond what's needed for alignment?](https://stackoverflow.com/q/63009070) , but in this case it's a leaf function so it's just using space in the red zone (below RSP) without having to reserve it first. Still, touching memory farther down the stack than necessary could possibly trigger an unnecessary page fault or cache miss. – Peter Cordes Feb 17 '23 at 21:08

0 Answers0