我编写空程序来惹恼stackoverflow编码器,不是。我只是在探索 gnu 工具链。
现在以下内容对我来说可能太深了,但为了继续空程序传奇,我已经开始检查 C 编译器的输出,即 GNU 所消耗的东西。
gcc version 4.4.0 (TDM-1 mingw32)
测试.c:
int main()
{
return 0;
}
gcc -S 测试.c
.file "test.c"
.def ___main; .scl 2; .type 32; .endef
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
call ___main
movl $0, %eax
leave
ret
你能解释一下这里发生了什么吗?这是我理解它的努力。我已经使用了as
手册和我的 x86 ASM 知识:
.file "test.c"
是逻辑文件名的指令。.def
:根据文档“开始为符号名称定义调试信息”。什么是符号(函数名/变量?)以及什么样的调试信息?.scl
:文档说“存储类可能会标记符号是静态的还是外部的”。这与我从 C 中知道的静态和外部相同吗?那'2'是什么?.type
:存储参数“作为符号表条目的类型属性”,我不知道。.endef
: 没问题。.text
:现在这是有问题的,它似乎是一个叫做部分的东西,我已经读过它是代码的地方,但是文档并没有告诉我太多。.globl
“使符号对 ld 可见。” ,手册对此很清楚。_main:
这可能是我的主要功能的起始地址(?)pushl_
: 长(32 位)推送,将 EBP 放入堆栈movl
: 32 位移动。伪C:EBP = ESP;
andl
: 逻辑与。Pseudo-C:ESP = -16 & ESP
,我真的不明白这有什么意义。call
:将 IP 推入堆栈(因此被调用的过程可以找到返回的路径)并继续原处__main
。(什么是__main?)movl
:这个零必须是我在代码末尾返回的常量。MOV 将此零放入 EAX。leave
: 在 ENTER 指令 (?) 后恢复堆栈。为什么?ret
: 回到栈中保存的指令地址
感谢您的帮助!