2.1.2 GCC-x86
现在我们尝试同样的C/C++代码在linux中的GCC 4.4.1编译
gcc 1.c -o 1
下一步,在IDA反汇编的帮助下,我们看看main()函数是如何被创建的。
(IDA与MSVC一样,也是显示Intel语法)。
我也可以是GCC生成Intel语法的汇编代码,添加参数-S -masm=intel
汇编代码:
main proc near
var_10 = dword ptr -10h
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov eax, offset aHelloWorld ;` `"hello, world"
mov [esp+10h+var_10], eax
call _printf
mov eax, 0
leave
retn
main endp
结果几乎是相同的,"hello,world"
字符串地址(保存在data段的)一开始保存在EAX寄存器当中,然后保存到栈当中。
同样的在函数开始我们看到了
AND ESP, 0FFFFFFF0h
这条指令以16字节边界大小对齐ESP寄存器,这使得所有值的地址在栈上都会有相同的对齐方式。
SUB ESP,10H
在栈上分配16个字节。 这里其实只需要4个字节。
这是因为,分配堆栈的大小也被排列在一个16字节的边界。
该字符串的地址(或这个字符串指针),不使用PUSH指令,直接写入到堆栈空间。var_10,是一个局部变量,也是printf()的参数。
然后调用printf()函数。
不像MSVC,当gcc编译不开启优化,它使用MOV EAX,0
清空EAX,而不是更短的代码。
最后一条指令,LEAVE相当于MOV ESP,EBP和POP EBP两条指令。
换句话说,这相当于指令将堆栈指针(ESP)恢复,EBP寄存器到其初始状态。
这是必须的,因为我们在函数的开头修改了这些寄存器的值(ESP和EBP)(执行MOV EBP,ESP/AND ESP…)。
当前内容版权归 beginners.re 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 beginners.re .