理解空main()的翻译成装配体 [英] Understanding empty main()'s translation into assembly

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

问题描述

有人请解释一下GCC为这段代码做什么?它是什么?原始代码是:

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

如果编译器/汇编大师通过解释堆栈,寄存器和段初始化来开始我,我将不胜感激。我不能把头或尾的代码。

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。

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

我将忽略部分初始化。部分初始化的解释和基本上我覆盖的一切可以在这里找到:
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寄存器是堆栈指针。它保存堆栈顶部的内存位置。每次我们推栈时,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指向基址,esp指向顶端。所以栈看起来像:

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.

前两个步骤称为过程序言,或更常见的是 function prolog ,他们准备堆栈供局部变量使用。请参见底部的过程序列引用。

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将指针保存到堆栈中的旧堆栈框架。因为main是被调用的第一个函数,我不知道%ebp的先前值。

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,我们进入一个新的堆栈帧,因为我们输入新功能(主)。因此,我们必须设置一个新的栈帧基指针。我们使用esp中的值作为堆栈帧的开始。

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;指挥堆栈,我发现了不同的意见。我不太确定这是做什么的。我怀疑这是为了允许在堆栈上分配大指令(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,

http://gcc.gnu.org/ml/gcc/2008-01/msg00282.html


这个代码and的ESP与0xFFFF0000,
使堆栈与下一个
最低的16字节边界对齐。对Mingw的源代码

检查显示,这可能是出现在_main
例程中的SIMD
指令,它们仅在对齐的
地址上操作。由于我们的例程不
包含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.

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,存储main 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.

步骤10和11将堆栈中前4个分配字节中的值移动到eax,然后将其从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.

我们已到达 function epilogue 。也就是说,函数的返回堆栈指针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,离开集合esp到ebp的值,将堆栈的顶部移动到调用main之前的地址。然后它设置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

程序Prolog:


函数必须做的第一件事是
被称为过程prolog。它
首先用指令pushl%ebp
保存当前基指针
(ebp)(记住ebp是用于
的寄存器,用于访问函数参数和
局部变量)。现在,它使用指令
movl%esp,%ebp将
堆栈指针(esp)复制到基本
指针(ebp)。这允许您
访问函数参数,因为
从基指针中索引。本地
变量总是ebp的减法
,例如第一个局部变量的-4(%ebp)或
(%ebp)-4,
返回值是总是在4(%ebp)
或(%ebp)+4,每个参数或
参数在N * 4 + 4(%ebp),如
8第一个参数
旧的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

A真正伟大的堆栈溢出线程存在,这回答了这个问题的很多。
为什么在我的gcc输出中有额外的说明?

A really great stack overflow thread exists which answers much of this question. Why are there extra instructions in my gcc output?

有关x86机器代码说明的好参考可以在这里找到:
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

这是一个包含以下一些想法的讲座:
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天全站免登陆