GCC编译汇编
GCC compiled assembly
我正在尝试通过示例学习汇编语言,或者使用 -S 选项、intel 语法和禁用的 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"
我真正的问题是为什么 main 函数有任何处理器指令(push edp
、mov edp, esp
等)?这些是否必要(我想这将是 prepare/shut 关闭程序的一种数据管理方式,但我不确定)?为什么它不在 main 函数之后发出 ret
语句?还有为什么有两个主要功能 (_main & ___main)?
总结一下,为什么不就是这样呢?
.def _main
_main:
mov eax, 0 ;(for return integer)
ret
GCC spits out this
如果您真的让 main 函数做一些事情,这可能会更清楚一些,这很奇怪,包括调用另一个函数。
您编译的代码正在设置一个框架,通过该框架使用第一个操作码 mov ebp,esp 引用其堆栈变量。例如,如果您有可以用 ebp 和常量引用的变量,就会使用它。然后,它使用 AND 指令将堆栈对齐到 16 字节的倍数——也就是说,它不会使用提供的堆栈的 0 到 15 字节,这样 [esp] 对齐到 16 的倍数字节。这很重要,因为正在使用调用约定。
结束操作码leave将备份的基指针复制到堆栈指针的当前状态,然后用pop恢复原始基指针。
My real question is why does the main function have any processor instructions
它正在为您没有做的事情(但非平凡的程序会做的事情)做准备,并且没有制作它可以做的最优化的 "return 0" 程序。通过拥有一个基本指针,该指针主要是原始堆栈指针的备份,程序可以自由地将局部变量作为偏移量加上基本指针(包括您不使用的隐含内容,如参数计数、指向指向参数列表的指针和指向环境的指针),并且通过具有 16 的倍数的堆栈指针,程序可以根据其调用标准自由调用函数。
我正在尝试通过示例学习汇编语言,或者使用 -S 选项、intel 语法和禁用的 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"
我真正的问题是为什么 main 函数有任何处理器指令(push edp
、mov edp, esp
等)?这些是否必要(我想这将是 prepare/shut 关闭程序的一种数据管理方式,但我不确定)?为什么它不在 main 函数之后发出 ret
语句?还有为什么有两个主要功能 (_main & ___main)?
总结一下,为什么不就是这样呢?
.def _main
_main:
mov eax, 0 ;(for return integer)
ret
GCC spits out this
如果您真的让 main 函数做一些事情,这可能会更清楚一些,这很奇怪,包括调用另一个函数。
您编译的代码正在设置一个框架,通过该框架使用第一个操作码 mov ebp,esp 引用其堆栈变量。例如,如果您有可以用 ebp 和常量引用的变量,就会使用它。然后,它使用 AND 指令将堆栈对齐到 16 字节的倍数——也就是说,它不会使用提供的堆栈的 0 到 15 字节,这样 [esp] 对齐到 16 的倍数字节。这很重要,因为正在使用调用约定。
结束操作码leave将备份的基指针复制到堆栈指针的当前状态,然后用pop恢复原始基指针。
My real question is why does the main function have any processor instructions
它正在为您没有做的事情(但非平凡的程序会做的事情)做准备,并且没有制作它可以做的最优化的 "return 0" 程序。通过拥有一个基本指针,该指针主要是原始堆栈指针的备份,程序可以自由地将局部变量作为偏移量加上基本指针(包括您不使用的隐含内容,如参数计数、指向指向参数列表的指针和指向环境的指针),并且通过具有 16 的倍数的堆栈指针,程序可以根据其调用标准自由调用函数。