【发布时间】:2012-04-03 20:55:07
【问题描述】:
我有一个简单的代码:
void func()
{
func2();
}
我省略了 func2 和 main 的实现,因为它们无关紧要。然后我用windbg跟踪汇编,下面是执行“func2()”时汇编代码的输出:
eax=cccccccc ebx=7ffd6000 ecx=00000000 edx=00000001 esi=01faf760 edi=0012ff68
eip=004113f0 esp=0012fe98 ebp=0012ff68 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
SimpleStack!func:
004113f0 55 push ebp
0:000> t
eax=cccccccc ebx=7ffd6000 ecx=00000000 edx=00000001 esi=01faf760 edi=0012fe94
eip=0041140e esp=0012fdc8 ebp=0012fe94 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
SimpleStack!func+0x1e:
0041140e e83dfcffff call SimpleStack!ILT+75(_func2) (00411050)
我们可以看到执行push ebp之前esp = 0012fe98, and ebp=0012ff68,但是执行push ebp之后esp=0012fdc8, ebp=0012fe94?,所以我有两个问题: 1. 推测push code应该只影响esp,为什么ebp也变了? 2. 推测push ebp会push 4字节入栈,所以esp的值应该减4,但是我们看到这里esp的值减了208字节?为什么?
【问题讨论】:
-
它没有。
push ebp完全按照它在锡上说的做。请注意,如果只执行了推送,eip 增加了 1E,它只会增加 1。显然,执行的不仅仅是推送。 -
这里发生了其他事情。 EIP 之间的差异 (0041140e - 004113f0) = 1E 字节。太大而不能成为一条指令。你有多个线程在运行吗?
-
@adelphus:你是对的。只需在
004113f0 .. 0041140e之间反汇编,你会发现一个序列(在此处使用 Intel 语法):PUSH EBP; MOV EBP, ESP; PUSH <other reg>; ...; SUB ESP, ...;这是编译器生成的函数入口代码(称为函数序言),它使代码实现通常的C调用约定/ABI。在函数的/return 末尾,您会找到一个相应的块ADD ESP, ...; POP ...; LEAVE; RET,它撤消了这一切。 -
@wangshuaijie: 变化
EBP不是PUSH EBP而是遵循 的指令 - 这将是MOV EBP, ESP.这就是为什么EBP中的新值与func()入口处ESP的初始值相差四个字节。如前所述,检查你的反汇编。 -
@all,恩,你们说得有道理,也许在执行push ebp的过程中,编译器在代码序列中插入了一些windbg没有显示的汇编代码,我会尝试更多看看。
标签: assembly x86 windbg stack-pointer