我正在阅读这本书Hacking: The Art of Exploitation , 2nd Edition 和简单的 C 程序
#include <stdio.h>
int main()
{
int i;
for (i = 0; i < 10; i++)
{
puts("Hello, world!\n");
}
return 0;
}
书中列出了 gdb 调试会先修改 ebp 寄存器:
(gdb) x/i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
正如它解释的那样, 这条汇编指令会将值 0 移动到位于 EBP 寄存器中存储的地址的内存中,减 4。这是 C 变量 i 存储在内存中的位置;i 被声明为在 x86 处理器上使用 4 字节内存的整数
这对我来说很有意义,但是当我在“非常旧的 I386”Linux 笔记本电脑上测试确切的步骤时,我得到了以下结果:
(gdb) x/i $eip => 0x4011b6 <main+29>: mov DWORD PTR [ebp-0xc],0x0
所以在我的笔记本电脑上,它显示的是 [ebp-0xc],而不是 [ebp-4]。根据我的理解,“0xc”作为十六进制将是 12,所以它将是 12 字节?如果是这样,为什么?
这是我笔记本电脑上这个简单程序(gdb)反汇编主程序的整个汇编转储
Dump of assembler code for function main:
0x00401199 <+0>: lea ecx,[esp+0x4]
0x0040119d <+4>: and esp,0xfffffff0
0x004011a0 <+7>: push DWORD PTR [ecx-0x4]
0x004011a3 <+10>: push ebp
0x004011a4 <+11>: mov ebp,esp
0x004011a6 <+13>: push ebx
0x004011a7 <+14>: push ecx
0x004011a8 <+15>: sub esp,0x10
0x004011ab <+18>: call 0x4010a0 <__x86.get_pc_thunk.bx>
0x004011b0 <+23>: add ebx,0x2e50
=> 0x004011b6 <+29>: mov DWORD PTR [ebp-0xc],0x0
0x004011bd <+36>: jmp 0x4011d5 <main+60>
0x004011bf <+38>: sub esp,0xc
0x004011c2 <+41>: lea eax,[ebx-0x1ff8]
0x004011c8 <+47>: push eax
0x004011c9 <+48>: call 0x401030 <puts@plt>
0x004011ce <+53>: add esp,0x10
0x004011d1 <+56>: add DWORD PTR [ebp-0xc],0x1
0x004011d5 <+60>: cmp DWORD PTR [ebp-0xc],0x9
0x004011d9 <+64>: jle 0x4011bf <main+38>
0x004011db <+66>: mov eax,0x0
0x004011e0 <+71>: lea esp,[ebp-0x8]
0x004011e3 <+74>: pop ecx
0x004011e4 <+75>: pop ebx
0x004011e5 <+76>: pop ebp
0x004011e6 <+77>: lea esp,[ecx-0x4]
0x004011e9 <+80>: ret
End of assembler dump.