我试图通过示例学习汇编语言,或者用-S选项编译简单的C文件,使用intel语法,并禁用CFI调用(其他任意方式都是非常混乱的)。
我的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发布于 2016-10-13 01:08:17
GCC说了这句话
如果你真的让你的主要功能做一些事情,奇怪的是,包括调用另一个函数,这可能会更清楚一些。
您的编译代码正在设置一个框架,通过该框架引用第一个操作码mov (尤指p)的堆栈变量。例如,如果有可以用ebp和常量引用的变量,就会使用这种方法。然后,它将堆栈与AND指令对齐为16字节的倍数--也就是说,它将不使用所提供堆栈的0到15字节,因此esp被对齐为16字节的倍数。这一点很重要,因为正在使用调用约定。
结束操作码将备份的基本指针复制到堆栈指针的当前状态上,然后用pop还原原始基指针。
我真正的问题是,为什么主函数有处理器指令?
它正在设置一些您没有做的事情(但那些非平凡的程序会做),并且没有做它所能做的最优化的“返回0”程序。通过拥有一个基本指针(主要是原始堆栈指针的备份),程序可以自由地将局部变量作为偏移量加上基指针(包括参数计数、指向参数列表指针的指针和指向环境的指针等不使用的隐含内容),通过拥有16倍的堆栈指针,程序可以根据其调用标准自由地调用函数。
https://stackoverflow.com/questions/40010107
复制相似问题