【发布时间】:2021-05-11 10:15:05
【问题描述】:
我正在读这本书 黑客:剥削的艺术,第 2 版 并在简单的 C 程序中
#include <stdio.h>
int main()
{
int i;
for (i = 0; i < 10; i++)
{
puts("Hello, world!\n");
}
return 0;
}
书上列出gdb debug会先修改ebp寄存器:
(gdb) x/i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
正如它所解释的那样 这条汇编指令会将 0 的值移动到位于 在存储在 EBP 寄存器中的地址,负 4。这是 C 变量 能够 i 存储在内存中; i 被声明为一个使用 4 个字节的整数 x86 处理器上的内存
这对我来说很有意义,但是当我在“非常旧的 I386”Linux 笔记本电脑上测试确切的步骤时,我得到了以下结果:
(gdb) x/i $eip => 0x4011b6 <main+29>: mov DWORD PTR [ebp-0xc],0x0
所以在我的笔记本电脑上,它显示的是 [ebp-0xc],而不是 [ebp-4]。 根据我的理解,“0xc”作为十六进制将是 12,所以它将是 12 字节?如果有,为什么?
这是我笔记本电脑上这个简单程序的整个汇编转储 (gdb) 反汇编 main
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.
【问题讨论】:
-
你能发布你的代码吗?你在一个函数内吗?例如,那些额外的 8 个字节可能已为返回值和本地参数保留。
-
代码很简单
code(gdb) list main 1 #include2 3 int main() 4 { 5 int i; 6 for (i = 0; i code -
我绝对需要完善我的汇编程序 :) 无论如何,请考虑一些事情。 1)您正在调试模式下编译它,不是吗? 2)将您的代码移动到一个函数中,只是为了测试
ebp-0x4确实被使用了。 3)main有点特殊功能。我想知道argc和argv是否与这些额外的8 个字节有关(尽管它们是参数,应该用ebp+...访问) -
另外,您使用的是什么编译器?编译行是什么?
-
您的编译器只是碰巧将变量放置在与本书作者使用的编译器不同的堆栈偏移处。这不应该让人感到意外——不同的编译器版本、选项、操作系统、配置选择等可能会导致这些事情发生变化。造成这种情况的确切原因很复杂,但对于理解您的实际应用程序代码的工作方式并不重要。