我现在正在学习汇编语言。我从中学习的书中的代码示例都是在x86 32位机器(我认为)上用gcc编译的。为了使我的输出与书中的输出相匹配,我使用" gcc -m32"编译了我的简单helloworld.c。
#include <stdio.h>
int main(){
int i;
for(i=0;i<10;i++){
printf("Hello World!\n");
}
return 0;
}
我从运行&#34; objdump -D a32.out |得到的输出grep -A20 main.:"看起来像这样:
0000051d <main>:
51d: 8d 4c 24 04 lea 0x4(%esp),%ecx
521: 83 e4 f0 and $0xfffffff0,%esp
524: ff 71 fc pushl -0x4(%ecx)
527: 55 push %ebp
528: 89 e5 mov %esp,%ebp
52a: 53 push %ebx
52b: 51 push %ecx
52c: 83 ec 10 sub $0x10,%esp
52f: e8 ec fe ff ff call 420 <__x86.get_pc_thunk.bx>
534: 81 c3 cc 1a 00 00 add $0x1acc,%ebx
53a: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
541: eb 16 jmp 559 <main+0x3c>
543: 83 ec 0c sub $0xc,%esp
546: 8d 83 f0 e5 ff ff lea -0x1a10(%ebx),%eax
54c: 50 push %eax
54d: e8 5e fe ff ff call 3b0 <puts@plt>
552: 83 c4 10 add $0x10,%esp
555: 83 45 f4 01 addl $0x1,-0xc(%ebp)
559: 83 7d f4 09 cmpl $0x9,-0xc(%ebp)
55d: 7e e4 jle 543 <main+0x26>
它错过了我得到的输出中的前三行,除了接下来的两行外,它看起来并不像它。这是为什么 ?如何更改我的编译器/反汇编设置以使其看起来相似?
答案 0 :(得分:2)
默认情况下,您的编译器配置为生成与位置无关的二进制文件,这会导致与本书的显着差异。 (这是最近的GCC开发)。
如果禁用此功能,您将更接近本书:
gcc -fno-pie -no-pie -m32 hello.c
正如其他人所说的,不能保证你会得到与本书中相同的代码,除非你得到完全相同的编译器内置完全相同的配置。
答案 1 :(得分:2)
与gcc -m32
一起运行的相同版本的gcc,无论在x86-64主机还是i386主机上运行,都应该是相同的。或者从ARM主机交叉编译!
区别在于gcc版本和默认设置。 (@Employed Russian指出,主要的一点是你的gcc默认启用了-fpie
。相关:32-bit absolute addresses no longer allowed in x86-64 Linux?)默认情况下,PIE默认为32位有点不好代码也不仅仅是64,因为在32位模式下额外的开销更为显着(没有RIP相对寻址。)
除了-fno-pie
之类的配置之外,不同版本的gcc会产生不同的代码。
无论如何,如果您真的想要与书中的内容相匹配,请尝试使用相同版本的gcc。 (希望他们提到这一点?如果没有,请查看发布的年份以获得粗略的暗示)。 您可以在http://gcc.godbolt.org/ 上尝试将每个gcc版本恢复到4.4。
这里有关于Godbolt的a link to your sample code,其中包含编译器asm输出和两个独立输出窗格中二进制文件的反汇编,两者都禁用了优化。
请注意,Matt Godbolt在没有default-pie
配置的情况下配置gcc,但是您可以使用-fpie
来获取asm,就像在桌面上一样。
请注意,对于未优化的代码,与您启用优化相比,它更依赖于gcc的内部。即-O0
有点让你看看gcc&#34;如何思考&#34;你的程序,因为它甚至没有尝试优化。 (另外它会在每个语句之间溢出/重新加载以支持使用调试器更改变量;这是为什么它如此缓慢的原因之一:它故意将一个球和链子捆绑到你的所有这些额外的存储/重新加载使得阅读更加困难;我通常会查看-O2
或-O3
输出。另请参阅How to remove "noise" from GCC/clang assembly output?)