GCC编译汇编
我尝试通过示例学习汇编语言,或者使用-S选项,英特尔语法和CFI调用禁用(使用其他免费方式非常混淆,使用GCC编译简单C文件)
我的C文件实际上只是int main() {return 0;}
,但GCC吐出这个:
.file "simpleCTest.c"
.intel_syntax noprefix
.def ___main; .scl 2; .type 32; .endef
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
push ebp
mov ebp, esp
and esp, -16
call ___main
mov eax, 0
leave
ret
.ident "GCC: (GNU) 5.3.0"
我真正的问题是为什么主函数有任何处理器指令( push edp
, mov edp, esp
等)? 这些甚至是必要的(我猜这将是一种数据管理来准备/关闭程序,但我不确定)? 为什么不在主函数之后发出ret
语句? 还有为什么有两个主要功能(_main&___main)?
总而言之,为什么它不仅仅是这样?
.def _main
_main:
mov eax, 0 ;(for return integer)
ret
GCC吐出这个
这可能会更清楚一点,如果你真的让你的主要功能做了一些奇怪的事情,包括调用另一个函数。
您的编译代码设置了一个框架,通过该框架可以通过第一个操作码mov ebp,esp引用其堆栈变量。 例如,如果您有可以用ebp和常量引用的变量,则可以使用这种方法。 然后,使用AND指令将堆栈对齐到16个字节的倍数,也就是说,它将不会使用所提供的堆栈的0到15个字节,因此[esp]被对齐到16的倍数字节。 由于使用的调用约定,这一点很重要。
结束操作码将备份的基本指针复制到堆栈指针的当前状态,然后使用弹出来恢复原始基本指针。
我真正的问题是为什么主函数有任何处理器指令
它为你不做的事情设置了东西(但是那些不重要的程序会这样做),并且没有做出它可能的最优化的“return 0”程序。 通过拥有一个基本指针,该指针大多是原始堆栈指针的备份,程序可以自由地将局部变量作为偏移量加上基本指针(包括默认的东西,例如参数计数,指向指向参数列表的指针以及指向环境的指针),并且具有16的倍数的堆栈指针,程序可以根据其调用标准自由调用函数。
链接地址: http://www.djcxy.com/p/86795.html