首页 > 解决方案 > 为什么 push 指令会改变 rsp 的值?

问题描述

我正在检查 Ericksons Hacking: The Art of Exploitation 中的这段代码片段:

void test_function(int a, int b, int c, int d) {
        int flag;
        char buffer[10];
        flag = 31337;
        buffer[0] = 'A';
}

int main() {
        test_function(1, 2, 3, 4); 
}
gcc -g stack_example.c

gdb -q ./a.out

gef➤list main


     0x555555555192 <main+0>         endbr64 
       0x555555555196 <main+4>         push   rbp
       0x555555555197 <main+5>         mov    rbp, rsp
     → 0x55555555519a <main+8>         mov    ecx, 0x4
       0x55555555519f <main+13>        mov    edx, 0x3
       0x5555555551a4 <main+18>        mov    esi, 0x2
       0x5555555551a9 <main+23>        mov    edi, 0x1
       0x5555555551ae <main+28>        call   0x555555555149 <test_function>
       0x5555555551b3 <main+33>        mov    eax, 0x0

我在 main 和 test_function 处设置断点。当 break main 我得到以下输出:

gef➤  i r rsp rbp rip

    rsp            0x7fffffffdfc8      0x7fffffffdfc8
    rbp            0x0                 0x0
    rip            0x555555555192      0x555555555192 <main>
gef➤ x/8i $rip

       0x555555555192 <main>:   endbr64 
       0x555555555196 <main+4>: push   rbp
       0x555555555197 <main+5>: mov    rbp,rsp
       0x55555555519a <main+8>: mov    ecx,0x4
       0x55555555519f <main+13>:    mov    edx,0x3
       0x5555555551a4 <main+18>:    mov    esi,0x2
       0x5555555551a9 <main+23>:    mov    edi,0x1
       0x5555555551ae <main+28>:    call   0x555555555149 <test_function>

gef➤continue

现在,当我在 test_function 处中断时,寄存器包含:

gef➤  i r rsp rbp rip

    **rsp            0x7fffffffdfc0      0x7fffffffdfc0**
    **rbp            0x7fffffffdfc0      0x7fffffffdfc0**
    rip            0x55555555519a      0x55555555519a <main+8>

我的问题是,为什么寄存器 rsp在这些指令之后会从0x7fffffffdfc8变为?0x7fffffffdfc0

    0x555555555196 <main+4>         push   rbp
    0x555555555197 <main+5>         mov    rbp, rsp

标签: cassemblyx86-64

解决方案


该指令push rbp完成与 相同的操作sub rsp, 8; mov QWORD PTR[rsp], rbp;。它首先将堆栈指针 ( rsp) 向上移动 8 个字节(这是因为 x86-64 中寄存器的大小是 8 个字节,即 64 位),然后将寄存器的值移动到它指向的内存位置。因此,rsp原来的 值0x7fffffffdfc8变为0x7fffffffdfc0,比以前小 8。


推荐阅读