海湾合作委员会的会输出的一个空的程序x86,win32
题
我写空的计划激怒了地狱的计算器编码,不。我只是探索gnu工具.
现在可能有下列太深了我,但continuie空节目的传奇故事我已经开始审查本输出的C编译器,GNU作为消耗。
gcc version 4.4.0 (TDM-1 mingw32)
测试。c:
int main()
{
return 0;
}
海湾合作委员会-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
手册和我最小的x86ASM知识:
.file "test.c"
是该指令的逻辑文件。.def
:根据文档 "开始界定调试信息的一个符号的名字".什么是一个符号(a function name/变量?) 什么样的调试的信息?.scl
:文件说 "储存的类可能标志是否符号是静态的或外部的".这是相同的 静 和 外 我知道从C?这是什么'2'?.type
:商店的参数 "作的类属性的一个符号表入口", 我没有任何线索。.endef
:没有问题。.text
:现在这是有问题的,这似乎是一些所谓的部分我已经阅读,它的地方代码,但是该文件没告诉我太多。.globl
"使符号可见ld。", 手册是很清楚这一点。_main:
这可能是起始的地址(?) 我的主要功能pushl_
:长(32位)推动,这地方EBP在栈movl
:32位的移动。伪C:EBP = ESP;
andl
:逻辑与。伪C:ESP = -16 & ESP
, 我不真的看到什么点。call
:推动知识产权的堆(所以被称为过程可以找到它的方式回),并继续在那里__main
是。(什么是__主要?)movl
:这种零必须是恒定的,我在结束我的代码。该章的地方,这种零入EAX.leave
:恢复叠之后,该指令(?).为什么?ret
:回到指令地址保存栈
谢谢你的帮助!
解决方案
.文件"测试。c"
命令开始。是指示汇编器。这只是说这是"文件。c",这些信息可以导出的调试信息的exe。
.def___主;.scl2;.类型32;.endef
.清晰的指示,定义了一个调试的符号。scl2装置存储2类(外部存储类)。类型32说这sumbol是一个功能。这些数字将由pe-。exe-格式
___主要功能是所谓的引导,海湾合作委员会的需求(这就不喜欢的东西跑c++静的初始化程序和其他家务需要的)。
.text
开始一个文字段代码的生活在这里。
.globl_main
定义_main符号作为全球,这将使它可见的接头和其他的模块,该模块的链接。
.def _main; .scl 2; .type 32; .endef
同样的事情,因为_main,创造了调试的符号说明_main是一个功能。这可以用于通过调试器。
_main:
开始一个新的标签(这将结束一个地址)。。globl指令以上,使这个地址看到其他实体。
pushl %ebp
节约的旧框架的指针(ebp登记册)的堆(因此可将它放回在地方当此功能结束)
movl %esp, %ebp
移动指针的ebp登记册。ebp通常被称为框架的指针,指顶部的堆值在当前的"框架"(功能通常),(参见变量上堆通过ebp可以帮助调试器)
电平$-16,%esp
阿富汗国家发展战略的堆与fffffff0其effectivly赞同它在a16byte边界。访问结盟值堆速度远远超过如果他们不结盟.所有这些前面的说明是相当多的一个标准功能的序幕。
call ___main
调___主要功能,这将做初始化的东西,海湾合作委员会的需要。呼吁将推动目前的指令指堆和跳跃到地址___主
movl $0, %eax
移0至eax,(0return0;)eax是用来保持功能返回值的呼吁《公约》。
离开
假指令是很多缩写
movl ebp,esp popl ebp
即它"撤消"做的东西在开始功能的恢复框架的指针和堆以前的状态。
ret
回到谁叫这个功能。它会弹出指令的指令从栈(其相应的电话指示将有放在那里)和跳跃。
其他提示
有一个非常类似的工作概述: http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax
你已经想通了它的大部分--我只会使附加说明的重点和补充。
__main
是一个子程序,在GNU标准图书馆的各种开始初始化。它不是严格必要的C节目,但是需要在情况的C码是联C++。
_main
是你的主要的子程序。作为两个 _main
和 __main
是代码的位置他们有同样的存储类别和类型。我没有挖出来的定义 .scl
和 .type
还没有。你可以得到一些照明,通过限定的几个全球变量。
第三个指示设置了一堆框架,这是一个技术术语的储存工作的一个子程序--地方和暂时的变量的大部分。推 ebp
节省的基地呼叫者的堆的框架。把 esp
入 ebp
设置我们堆的框架。的 andl
对齐的叠框架的16个字节的边界只是在任何情况下,地方变量上堆需要16字节对准(对于x86单指令的指令要求准,但对准并加速普通类型,例如 int
s和 float
s.
在这一点上,你通常会希望 esp
获得向下移动在内存分配堆空间用于当地变量。你的 main
有没有使海湾合作委员会不打扰。
呼叫 __main
是特殊的主要入境点和通常不会出现在子程序。
其余部分则为你推测。注册 eax
是的地方,把整数返回代码在二的规范。 leave
撤消的框架和堆叠 ret
回去呼叫者。在这种情况下,呼叫者的低水平C运行时,它将会做更多的魔术(如呼叫 atexit()
职能,设置退出的代码处理,并要求操作系统,以终止进程。
关于那个 电平$-16,%esp
- 32位:-16在小数点等于0xfffffff0在进制表示
- 64位:-16在小数点等于0xfffffffffffffff0在进制表示
因此,它会掩盖掉最后4位ESP(顺便说一句:2**4等于16个),并将保留所有其他位(无论如果目标系统为32或64位)。
进一步的 andl $-16,%esp
, 这工作是因为设置的位低到零将始终调整 %esp
下 在价值,并且该堆的增长下x86。
我没有所有答案但我可以解释我所知道的。
ebp
所使用的功能以储存的初始状态 esp
在其流动、参考其中的论点传递给功能并在那里被自己的地方变量。第一件事情,功能不是拯救地位的给予 ebp
做 pushl %ebp
, 它是至关重要的功能,使该呼叫,并于替换它通过其自身的当前堆的位置 esp
做 movl %esp, %ebp
.零的最后4位 ebp
在这一点是海湾合作委员会具体的,我不知道为什么这个编译器。它的工作没有这样做。现在,最后我们进入业务, call ___main
, 谁是__主要?我不知道...也许更多的海湾合作委员会的具体程序,最后的只有一件事你主()does,设置返回值为0 movl $0, %eax
和 leave
这是一样做着 movl %ebp, %esp; popl %ebp
恢复 ebp
状态,然后 ret
来完成。 ret
pops eip
并继续螺纹流从这一点出发,无论它是(作为其主要的(),这ret可能导致某些核心程序,其处理结束的程序)。
它是所有关于管理。我写了一个详细教程有关如何堆使用的前一段时间,它将有助于解释为什么所有这些事情。但其在葡萄牙语...