了解空的main()的翻译成汇编 [英] Understanding empty main()'s translation into assembly

查看:236
本文介绍了了解空的main()的翻译成汇编的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能有人请解释一下GCC是做这块code的?它是什么初始化?原来的code是:

Could somebody please explain what GCC is doing for this piece of code? What is it initializing? The original code is:

#include <stdio.h>
int main()
{

}

和它被翻译为:

    .file	"test1.c"
    .def	___main;	.scl	2;	.type	32;	.endef
    .text
.globl _main
    .def	_main;	.scl	2;	.type	32;	.endef
_main:
    pushl	%ebp
    movl	%esp, %ebp
    subl	$8, %esp
    andl	$-16, %esp
    movl	$0, %eax
    addl	$15, %eax
    addl	$15, %eax
    shrl	$4, %eax
    sall	$4, %eax
    movl	%eax, -4(%ebp)
    movl	-4(%ebp), %eax
    call	__alloca
    call	___main
    leave
    ret

如果一个编译器/组装大师让我通过解释堆栈开始我将不胜感激,注册和部分初始化。我不能让头部或尾部出code的。

I would be grateful if a compiler/assembly guru got me started by explaining the stack, register and the section initializations. I cant make head or tail out of the code.

编辑:
我用gcc 3.4.5。和命令行参数是gcc -S test1.c

I am using gcc 3.4.5. and the command line argument is gcc -S test1.c

感谢您,
kunjaan。

Thank You, kunjaan.

推荐答案

我应该说,我仍然在学习assmebly我的所有评论preface。

I should preface all my comments by saying, I am still learning assmebly.

我会忽略段初始化。一种用于初始化部分,基本上一切我盖的解释可以在这里找到:
<一href=\"http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax\">http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax

I will ignore the section initialization. A explanation for the section initialization and basically everything else I cover can be found here: http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax

在EBP 注册是的堆栈帧基指针,因此BP。它存储一个指向当前堆栈的开头。

The ebp register is the stack frame base pointer, hence the BP. It stores a pointer to the beginning of the current stack.

ESP寄存器是堆栈指针。它保存在堆栈的顶部的存储器位置。每个我们推东西在栈上时尤被更新,以便它始终指向一个地址堆栈的顶部。

The esp register is the stack pointer. It holds the memory location of the top of the stack. Each time we push something on the stack esp is updated so that it always points to an address the top of the stack.

所以EBP指向底座和尤指向上方。因此,堆栈如下:

So ebp points to the base and esp points to the top. So the stack looks like:

esp -----> 000a3   fa
           000a4   21
           000a5   66
           000a6   23
esb -----> 000a7   54

如果您在堆栈上推E4这是发生了什么:

If you push e4 on the stack this is what happens:

esp -----> 000a2   e4
           000a3   fa
           000a4   21
           000a5   66
           000a6   23
esb -----> 000a7   54

注意,堆栈向低地址,这个事实将低于重要的。

Notice that the stack grows toward lower addresses, this fact will be important below.

前两个步骤被称为步骤序言或更常见的功能序言,他们prepare栈供本地变量使用。见过程序言报价在底部。

The first two steps are known as the procedure prolog or more commonly the function prolog, they prepare the stack for use by local variables. See procedure prolog quote at the bottom.

在步骤1中,我们通过调用保存的指针堆栈上的老栈帧,
pushl%ebp的。由于主要是调用的第一个功能,我不知道什么的%ebp点previous值了。

In step 1 we save the pointer to the old stack frame on the stack by calling, pushl %ebp. Since main is the first function called, I have no idea what the previous value of %ebp points too.

步骤2,我们是因为我们正在进入一个新的功能(主)进入一个新的堆栈帧。因此,必须建立一个新的堆栈帧基指针。我们使用在尤值是我们堆栈帧的开头。

Step 2, We are entering a new stack frame because we are entering a new function (main). Therefore, we must set a new stack frame base pointer. We use the value in esp to be the beginning of our stack frame.

步骤3中分配的8个字节的堆叠上的空间。如我们上面提到的,堆栈增长朝向低地址,因此,通过8中减去,由8个字节移动堆栈的顶部。

Step 3. Allocates 8 bytes of space on the stack. As we mentioned above, the stack grows toward lower addresses thus, subtracting by 8, moves the top of the stack by 8 bytes.

步骤4; Alligns栈中,我发现在这个不同的意见。我真的不知道到底是什么做到这一点。我怀疑这是为了让大型指令(SIMD)在堆栈上分配,

Step 4; Alligns the stack, I've found different opinions on this. I'm not really sure exactly what this is done. I suspect it is done to allow large instructions (SIMD) to be allocated on the stack,

<一个href=\"http://gcc.gnu.org/ml/gcc/2008-01/msg00282.html\">http://gcc.gnu.org/ml/gcc/2008-01/msg00282.html

这code和与0xFFFF0000地址ŞESP,
  与下一个对准堆栈
  最低16字节边界。一个
  称为Mingw的源$ C ​​$ C检查
  揭示了,这可能是对于SIMD
  出现在_main指示
  程序,该程序仅在对齐操作
  地址。由于我们的例程不
  包含SIMD指令,这一行
  是不必要的。

This code "and"s ESP with 0xFFFF0000, aligning the stack with the next lowest 16-byte boundary. An examination of Mingw's source code reveals that this may be for SIMD instructions appearing in the "_main" routine, which operate only on aligned addresses. Since our routine doesn't contain SIMD instructions, this line is unnecessary.

<一个href=\"http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax\">http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax

步骤5到11似乎没有什么目的我。我找不到对谷歌任何解释。可能有人谁真正知道这个东西提供了一个更深入的了解。我听说这东西是用来对C的异常处理的传言。

Steps 5 through 11 seem to have no purpose to me. I couldn't find any explanation on google. Could someone who really knows this stuff provide a deeper understanding. I've heard rumors that this stuff is used for C's exception handling.

步骤5,存储的主要0的返回值,在eax中。

Step 5, stores the return value of main 0, in eax.

步骤6和7,我们在十六进制增加15至EAX未知原因。 EAX = 01111 + 01111 = 11110

Step 6 and 7 we add 15 in hex to eax for unknown reason. eax = 01111 + 01111 = 11110

步骤8我们eax中4位的位向右移。 EAX = 00001因为最后位是推卸年底00001 | 111.

Step 8 we shift the bits of eax 4 bits to the right. eax = 00001 because the last bits are shift off the end 00001 | 111.

步骤9我们eax中的比特移位4位到左侧,EAX = 10000

Step 9 we shift the bits of eax 4 bits to the left, eax = 10000.

步骤在栈到EAX上的第一个4字节分配10和11移动的值,然后从EAX移回。

Steps 10 and 11 moves the value in the first 4 allocated bytes on the stack into eax and then moves it from eax back.

步骤12和13设置C库。

Steps 12 and 13 setup the c library.

我们已经达到了函数尾声。也就是说,它返回堆栈指针,ESP和EBP到它们在被调用此函数之前的状态的功能的一部分。

We have reached the function epilogue. That is, the part of the function which returns the stack pointers, esp and ebp to the state they were in before this function was called.

步骤14,离开套尤指EBP的值,移动堆栈的顶部到它主要被称为前的地址。然后,它设置EBP指向我们第1步中保存在堆栈的顶部的地址。

Step 14, leave sets esp to the value of ebp, moving the top of stack to the address it was before main was called. Then it sets ebp to point to the address we saved on the top of the stack during step 1.

离开正好可以用下面的指令代替:

Leave can just be replaced with the following instructions:

mov  %ebp, %esp
pop  %ebp

步骤15,收益和退出功能。

Step 15, returns and exits the function.

1.    pushl       %ebp
2.    movl        %esp, %ebp
3.    subl        $8, %esp
4.    andl        $-16, %esp
5.    movl        $0, %eax
6.    addl        $15, %eax
7.    addl        $15, %eax
8.    shrl        $4, %eax
9.    sall        $4, %eax
10.   movl        %eax, -4(%ebp)
11.   movl        -4(%ebp), %eax
12.   call        __alloca
13.   call        ___main
14.   leave
15.   ret

序言步骤:

一个函数的第一件事要做
  被调用的过程序言。它
  首先保存当前基指针
  (EBP)与指令pushl%EBP
  (记住EBP是用于寄存器
  访问功能参数和
  本地变量)。现在,它的复制
  堆栈指针(ESP)到基
  指针(EBP)与指令
  MOVL%ESP,EBP%。这可以让你
  访问功能参数如
  从基指针索引。本地
  变量始终减法
  从EBP,如-4(%EBP)或
  (%EBP)-4-用于第一局部变量
  返回值始终为4(%EBP)
  或(EBP%)+4,每个参数或
  论点是N * 4 + 4(%EBP)如
  8(EBP%),为第一个参数,而
  老EBP为(%EBP)。

The first thing a function has to do is called the procedure prolog. It first saves the current base pointer (ebp) with the instruction pushl %ebp (remember ebp is the register used for accessing function parameters and local variables). Now it copies the stack pointer (esp) to the base pointer (ebp) with the instruction movl %esp, %ebp. This allows you to access the function parameters as indexes from the base pointer. Local variables are always a subtraction from ebp, such as -4(%ebp) or (%ebp)-4 for the first local variable, the return value is always at 4(%ebp) or (%ebp)+4, each parameter or argument is at N*4+4(%ebp) such as 8(%ebp) for the first argument while the old ebp is at (%ebp).

http://www.milw0rm.com/papers/52

一个真正伟大的堆栈溢出线程存在,回答多少这个问题。
<一href=\"http://stackoverflow.com/questions/499842/why-are-there-extra-instructions-in-my-gcc-output\">http://stackoverflow.com/questions/499842/why-are-there-extra-instructions-in-my-gcc-output

A really great stack overflow thread exists which answers much of this question. http://stackoverflow.com/questions/499842/why-are-there-extra-instructions-in-my-gcc-output

在x86机器code说明一个很好的参考可以在这里找到:
<一href=\"http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html\">http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html

A good reference on x86 machine code instructions can be found here: http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html

这其中包含了一些下面使用的想法的演讲:
<一href=\"http://csc.colstate.edu/bosworth/cpsc5155/Y2006_TheFall/MySlides/CPSC5155_L23.htm\">http://csc.colstate.edu/bosworth/cpsc5155/Y2006_TheFall/MySlides/CPSC5155_L23.htm

This a lecture which contains some of the ideas used below: http://csc.colstate.edu/bosworth/cpsc5155/Y2006_TheFall/MySlides/CPSC5155_L23.htm

下面是回答你的问题的另一个看法:
http://www.phiral.net/linuxasmone.htm

Here is another take on answering your question: http://www.phiral.net/linuxasmone.htm

这些来源没有说明一切。

None of these sources explain everything.

这篇关于了解空的main()的翻译成汇编的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆