$ 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)中有推送。我的问题是:
.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)"这是什么意思?
谢谢。
发布于 2010-10-26 04:40:21
无论使用什么变体,指令都被称为MOV。l后缀只是一个gcc / AT&T程序集约定,用于指定所需操作数的大小,在本例中为4个字节操作数。
在英特尔语法中--如果有任何歧义--通常不会在指令后缀上加上所需大小的指示器(例如BYTE、WORD、DWORD等)来标记内存参数,这只是实现相同目标的另一种方式。
89 55是MOV从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,,3sum是一个全局符号,它是一个函数。
.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)"发布于 2010-10-26 04:50:09
汇编程序列表和反汇编程序列表显示相同的代码,但使用不同的语法。附加的-l是gcc使用的语法变体。工具中有不同的语法(C编译器输出和反汇编器)显示了工具链的一个弱点。
偏移量11之和处的可拆卸性:显示的只是一些垃圾字节。下一个函数main的入口点是4字节对齐,这就造成了这个空白,充满了垃圾。
.statements的集合是由汇编程序的文档定义的。通常他们不会给出任何可执行的代码。
https://stackoverflow.com/questions/4020683
复制相似问题