2010-10-26 79 views
8
$ gcc -O2 -S test.c -----------------------(1) 
     .file "test.c" 
    .globl accum 
     .bss 
     .align 4 
     .type accum, @object 
     .size accum, 4 
    accum: 
     .zero 4 
     .text 
     .p2align 2,,3 
    .globl sum 
     .type sum, @function 
    sum: 
     pushl %ebp 
     movl %esp, %ebp 
     movl 12(%ebp), %eax 
     addl 8(%ebp), %eax 
     addl %eax, accum 
     leave 
     ret 
     .size sum, .-sum 
     .p2align 2,,3 
    .globl main 
     .type main, @function 
    main: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $8, %esp 
     andl $-16, %esp 
     subl $16, %esp 
     pushl $11 
     pushl $10 
     call sum 
     xorl %eax, %eax 
     leave 
     ret 
     .size main, .-main 
     .section .note.GNU-stack,"",@progbits 
     .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)" 

这是从这个C程序生成的汇编代码:分析汇编代码

#include <stdio.h> 
int accum = 0; 

int sum(int x,int y) 
{ 
    int t = x+y; 
    accum +=t; 
    return t; 
} 

int main(int argc,char *argv[]) 
{ 
    int i = 0,x=10,y=11; 
    i = sum(x,y); 
    return 0; 
} 

此外,这是由上述程序生成的目标代码:

$objdump -d test.o -------------------------(2) 

test.o:  file format elf32-i386 

Disassembly of section .text: 

00000000 <sum>: 
    0: 55      push %ebp 
    1: 89 e5     mov %esp,%ebp 
    3: 8b 45 0c    mov 0xc(%ebp),%eax 
    6: 03 45 08    add 0x8(%ebp),%eax 
    9: 01 05 00 00 00 00  add %eax,0x0 
    f: c9      leave 
    10: c3      ret 
    11: 8d 76 00    lea 0x0(%esi),%esi 

00000014 <main>: 
    14: 55      push %ebp 
    15: 89 e5     mov %esp,%ebp 
    17: 83 ec 08    sub $0x8,%esp 
    1a: 83 e4 f0    and $0xfffffff0,%esp 
    1d: 83 ec 10    sub $0x10,%esp 
    20: 6a 0b     push $0xb 
    22: 6a 0a     push $0xa 
    24: e8 fc ff ff ff   call 25 <main+0x11> 
    29: 31 c0     xor %eax,%eax 
    2b: c9      leave 
    2c: c3      ret 

理想情况下,列表(1)和(2)必须相同。但我看到 在列表(1)中存在movl,pushl等,而mov,推入 lising(2)。我的问题是:

  1. 这是在处理器上实际执行的正确汇编指令吗?
  2. 在上市(1),我看到这个开头:

.file "test.c" 
    .globl accum 
     .bss 
     .align 4 
     .type accum, @object 
     .size accum, 4 
    accum: 
     .zero 4 
     .text 
     .p2align 2,,3 
    .globl sum 
     .type sum, @function 

,这在端:

.size main, .-main 
      .section .note.GNU-stack,"",@progbits 
      .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)" 

这是什么意思?

谢谢。

回答

13

该指令被称为MOV无论使用什么变体。后缀l只是一个gcc/AT & T程序集约定来指定所需的操作数的大小,在这种情况下是4个字节的操作数。

在Intel语法 - 其中存在任何歧义 - 而不是后面添加的指令,通常与所需要的大小的指标标记的存储器的参数(例如​​,WORDDWORD等),这只是另一种方式达到同样的目的。

89 55MOV从32位寄存器EBP到32位寄存器ESP的正确字节序列。上市没有任何错误。


指定生成该汇编代码的文件从:

.file "test.c" 

说该accum是一个全球性的符号(具有外部链接C变量):

.globl accum 

下列字节应放置在bss部分,这是一个在对象文件中不占用空间但在运行时分配并归零的部分。

 .bss 

对齐的4字节边界上:

 .align 4 

它是一个对象(一个变量,而不是一些代码):

 .type accum, @object 

这四个字节:

 .size accum, 4 

这里是accum是定义了四个零字节。

accum: 
     .zero 4 

现在从bss部分切换到通常存储函数的文本部分。

 .text 

最多可添加三个填充字节,以确保我们在一个4字节(2^2)边界:

 .p2align 2,,3 

sum是一个全球性的象征,它是一个函数。

.globl sum 
     .type sum, @function 

main大小是 “这里” - “其中main开始”:

.size main, .-main 

这些已指定GCC堆栈特定的选项。通常,这是您选择拥有可执行堆栈(不是非常安全)或不是(通常是首选)的地方。

 .section .note.GNU-stack,"",@progbits 

确定哪些版本生成该组件的编译器:

 .ident "GCC: (GNU) 3.4.6 20060404 (Red Hat 3.4.6-9)" 
+0

+9,000。谢谢。关于GCC特定堆栈选项的一点很有帮助。 – kevinarpe 2015-02-13 04:31:27

0

汇编程序和反汇编列表显示相同的代码,但使用不同的语法。附加-l是gcc使用的语法变体。你在工具中有不同的语法(C编译器输出和反汇编)显示你的工具链的弱点。

在总和偏移量11处可拆卸地显示:仅显示一些垃圾字节。进入下一个函数main的入口点是4字节对齐的,这会产生这种差距,填满垃圾。

一堆.statements由汇编器的文档定义。通常他们不提供任何可执行代码。