0

我正在阅读一本关于 asm 的 C 书籍,并使用 GDB 查看寄存器和内存。问题是,当我编译和反汇编完全相同的源代码时(实际上是使用随书 cd 提供的源文件),汇编指令看起来与书中的内容有很大不同。这本书使用了英特尔风格的汇编,我将“设置反汇编英特尔”放在 gdb 中,所以不是那样......只是说明的顺序不同,有些完全不同,还有一些其他的怪癖。

例如,书中的 eip 寄存器中有一条 mov 指令:

(gdb) x/i $eip
mov DWORD PTR[ebp-4], 0x0

对应于在 for 循环中将变量 i 初始化为 0 (i = 0, i<10, i++)

但是,在我的 gdb 控制台中,断点位于同一位置(set break main; run)我看到了:

(gdb) x/i $eip
mov DWORD PTR[esp+0x1c], 0x0

请注意,它一起引用了一个不同的寄存器-如果我检查 esp 的值,则 esp 而不是 ebp,它本身就是 0x1c。但是,如果我尝试检查 0x1c 或 esp+0x1c 的内容,它会告诉我我无法查看这些地址

所以随着这本书的继续,我根本无法跟上,因为它开始跟踪 ebp、ebp-4 等中的内容,而在我的 asm 中似乎没有发生任何事情ebp 寄存器

这本书写于 2008 年,所以我无法想象它已经过时了,以至于 gcc 或 gdb 的版本更改会带来如此重大的变化(或者做到了?)......是否可能有一些编译器优化还是默认打开的东西会产生如此不同的结果?

提前致谢

编辑:奇怪。我尝试了每个建议,但没有任何效果。然后我做了 rm a.out 并重新编译,现在它工作正常(说明仍然与书不同,但我可以检查与书对应的地址;只要我能遵循相应的模式,一切都很好,不必是完全相同的 asm,那只会让它太容易了!)再次感谢您的所有帮助和建议。

4

3 回答 3

1

看起来你编译的代码是用 编译的-fomit-frame-pointers,它成为 GCC-4.6 的默认值。

尝试使用显式构建-fno-omit-frame-pointer。我希望结果看起来更接近书。

于 2012-02-09T05:42:54.730 回答
1

有一百万种事情可能导致这种情况。如果你在不同的架构上编译你的代码,我会期望这个(不,这甚至不一定意味着 32 位和 64 位——实际上任何不同的 CPU 架构都可以改变执行顺序,我将解释) . 如果你用优化编译你的程序,它将改变执行的顺序以最好地利用你的 CPU 的管道。这可能意味着添加一些 NOOP 指令,或完全重新排序它们(当然,在合理范围内)。此外,一些 CPU 有多种做事方式,一种方式通常比另一种更快(想到英特尔 LOOP 指令——现代编译器像瘟疫一样避免这条指令,因为它很糟糕)。如果一个寄存器比另一个更有效,它将使用它。

故事的寓意:出于学习目的,作者和读者都需要禁用所有优化。还有额外的奖励积分:使用相同版本的 gcc 和相同的平台。

于 2012-02-09T04:50:09.830 回答
0

这一切都将是非常平台和编译器特定的。恐怕你无能为力。

于 2012-02-09T04:48:51.127 回答