我正在阅读一本C书,它与asm有很多关系,并用GDB查看寄存器和内存。 问题是,当我编译和反汇编完全相同的源(实际上使用随书附带的源文件)时,汇编指令看起来与书中的内容有很大不同。 这本书使用英特尔风味的程序集,我在gdb中设置“set disassembly intel”,所以不是那样......只是指令的顺序不同,有些都是不同的,还有一些其他的怪癖。
例如,在书中,eip寄存器中有一条mov指令:
(gdb) x/i $eip
mov DWORD PTR[ebp-4], 0x0
对应于在for循环中将变量i初始化为0(i = 0,i <10,i ++)
但是,在我的gdb控制台中,断点位于同一位置(设置break main; run)我看到了:
(gdb) x/i $eip
mov DWORD PTR[esp+0x1c], 0x0
注意它一起引用了一个不同的寄存器 - 尤其是epp 如果我检查esp的值,它本身就是0x1c。但是,如果我尝试检查0x1c或esp + 0x1c处的内容,它会告诉我我无法查看这些地址
因此,随着本书的继续,我根本无法跟进,因为它开始跟踪ebp,ebp-4等中的内容,而在我的asm中似乎没有任何内容发生在ebp寄存器
这本书是在2008年写的,所以我无法想象它如此过时,gcc或gdb的版本更改会引入重大的改变(或者是吗?)......是否有可能存在一些编译器优化或默认情况下打开的东西产生了不同的结果?
提前致谢
编辑:奇怪。我尝试了每个建议,没有任何效果。然后我做了一个a.out并重新编译了新的,现在它工作正常(指令与书不同但我可以检查相应的书的地址;只要我可以遵循相应的模式一切都很好,不必是完全相同的,这只会让它变得太容易!) 再次感谢您的所有帮助和建议。
答案 0 :(得分:1)
有一百万件事可能导致这种情况发生。如果你在不同的架构上编译你的代码,我会期待这一点(不,这甚至不一定意味着32比64位 - 实际上任何不同的CPU架构都可以改变执行顺序,因为我和#39; ll解释)。如果使用优化编译程序,它将改变执行的顺序,以最好地利用CPU的管道。这可能意味着添加一些NOOP指令,或者完全重新排序它们(理所当然)。此外,一些CPU有多种处理方式,一种方式通常比另一种方式更快(想到英特尔LOOP指令 - 现代编译器避免像瘟疫这样的指令,因为它很可怕)。如果一个寄存器比另一个寄存器更有效,它将使用它。
故事的寓意:出于学习目的,作者和读者都需要禁用所有优化。还有额外的奖励积分:使用相同版本的gcc和相同的平台。
答案 1 :(得分:1)
看起来您编译的代码是使用-fomit-frame-pointers
编译的,这是GCC-4.6的默认代码。
尝试使用显式-fno-omit-frame-pointer
进行构建。我希望结果看起来更接近这本书。
答案 2 :(得分:0)
这将是非常平台和编译器特定的。我担心你无能为力。