I have the following assembly program:
.globl main
main:
push %rbp
mov %rsp, %rbp
movb $8, -1(%rbp)
movw $30, -4(%rbp)
mov -1(%rbp), %rax
add -4(%rbp), %rax
call func
pop %rbp
ret
func:
push %rbp
mov %rsp, %rbp
movl $7, -4(%rbp)
mov -4(%rbp), %rbx
pop %rbp
ret
When stepping through the program, after the call func
but before the push %rbp
when trying access the value of rbp
, which was previously $0x0800001e` (8 byte, 0 byte, 0 byte, 30 byte), it now shows all zeros:
>>> x/1xw $rbp-4
0x7fffffffe410: 0x00000000
Why does this occur? Does rbp
reset its value (though keeping its address) between function calls?
The value of RBP doesn't change. Each asm instruction only changes the architectural state of the machine (register + memory contents) in the ways documented in the manual. (Intel and AMD both publish PDF manuals; HTML extract of the instruction-set reference from IInel's PDF at https://www.felixcloutier.com/x86/)
You're dumping memory pointed-to by RBP, not printing the value of RBP. (Do that with p /x $rbp
. Or use GDB's TUI mode with layout reg
. See the bottom of https://stackoverflow.com/tags/x86/info for GDB tips).
The memory changes when call
pushes a return address. You didn't reserve any space for your local vars with sub $8, %rsp
for example, so RSP = RBP and the space below RSP is where push
and call
write.
That's why non-leaf functions can't use the red-zone (below RSP) for their local vars.