我写空的计划激怒了地狱的计算器编码,不。我只是探索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 节省的基地呼叫者的堆的框架。把 espebp 设置我们堆的框架。的 andl 对齐的叠框架的16个字节的边界只是在任何情况下,地方变量上堆需要16字节对准(对于x86单指令的指令要求准,但对准并加速普通类型,例如 ints和 floats.

在这一点上,你通常会希望 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 在其流动、参考其中的论点传递给功能并在那里被自己的地方变量。第一件事情,功能不是拯救地位的给予 ebppushl %ebp, 它是至关重要的功能,使该呼叫,并于替换它通过其自身的当前堆的位置 espmovl %esp, %ebp.零的最后4位 ebp 在这一点是海湾合作委员会具体的,我不知道为什么这个编译器。它的工作没有这样做。现在,最后我们进入业务, call ___main, 谁是__主要?我不知道...也许更多的海湾合作委员会的具体程序,最后的只有一件事你主()does,设置返回值为0 movl $0, %eaxleave 这是一样做着 movl %ebp, %esp; popl %ebp 恢复 ebp 状态,然后 ret 来完成。 ret pops eip 并继续螺纹流从这一点出发,无论它是(作为其主要的(),这ret可能导致某些核心程序,其处理结束的程序)。

它是所有关于管理。我写了一个详细教程有关如何堆使用的前一段时间,它将有助于解释为什么所有这些事情。但其在葡萄牙语...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top