assemblyx86-64calling-convention

Does the C runtime clear the home slots of args prior to function calls?


When you call a function from C/C++, that has some params smaller than 64bits, does the runtime zero out the stack memory at the home location of those params? Or does the top of each param contain garbage?

The space for each param is 8 bytes (64bits), but they might represent 8, 16, or 32bit values.

Assume that the params are not passed by register, as this question pertains to any param, not just the first 4.

void foobar(bool a, i32 b, float c, i64 d)
{
    int x = 0, y = 0, z = 0;    
}

----------------------------------------
# Stack Frame #

[... Previous StackFrame ...] // <HIGH ADDRESS>
[d]
[c]
[b]  // Do the top 32 most-significan-bits of param 'b' contain garbage, or zero?
[a]
[ReturnAddr]
[Saved rbp]
[x]
[y]
[z]


// read 'b' value -- if the top 32bits of 'b' contains garbage, rax has wrong value.
mov rax, qword ptr[rbp+24]

Solution

  • Firstly, no, there is no guarantee that the padding between parameters which are passed via the stack is zeroed out. This is specified e.g. in the System-V ABI, 3.2 Function Calling Sequence, which is used on Unix-like systems.

    However, it also doesn't really matter what is in the padding bytes. To read the value of a bool b that has been passed via the stack, the compiler could emit

    mov al, byte ptr[rbp+24]
    

    This ignores the upper 56 padding bits at the pointer. If the upper 56 bits of RAX should be zero, movzx could also be used as follows:

    movzx eax, byte ptr[rbp+24]