在《剥削艺术》示例中,对 [ebp-0xc] 而不是 [ebp-4] 感到困惑

Yon*_*ang 5 x86 assembly gcc

我正在阅读《黑客:剥削的艺术》一书,第二版,以及简单的 C 程序

#include <stdio.h>
int main()
{
    int i;  
    for (i = 0; i < 10; i++)
    {
        puts("Hello, world!\n");
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

书上列出gdb调试会先修改ebp寄存器:

(gdb) x/i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
Run Code Online (Sandbox Code Playgroud)

正如它所解释的, 这条汇编指令会将 0 的值移动到位于 EBP 寄存器中存储的地址减去 4 的内存中。这是 C 变量 i 存储在内存中的位置;i 被声明为在 x86 处理器上使用 4 字节内存的整数

这对我来说很有意义,但是当我在我的“非常旧的 I386”Linux 笔记本电脑上测试确切的步骤时,我得到的是:

(gdb) x/i $eip => 0x4011b6 <main+29>:   mov    DWORD PTR [ebp-0xc],0x0
Run Code Online (Sandbox Code Playgroud)

所以在我的笔记本电脑上,它显示 [ebp-0xc],而不是 [ebp-4]。根据我的理解,“0xc”作为十六进制将是12,所以它将是12个再见?如果是这样,为什么?

这是我的笔记本电脑上这个简单程序(gdb)反汇编主程序的整个汇编转储

(gdb) x/i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
Run Code Online (Sandbox Code Playgroud)

Jos*_*hua 5

sub esp,0x10

在堆栈上为变量和其他内容分配了 16 个字节(相当于四个寄存器)的空间。

mov DWORD PTR [ebp-0xc],0x0

似乎是对 slot 的第一个引用ebp-0xc,并且它被初始化为零。查看后cmp DWORD PTR [ebp-0xc],0x9main+60确定这是i = 0来自循环的初始化部分for

编译器可以将变量放在它想要的位置,并且虽然是确定性的,但它会随着编译器的补丁版本而变化。