$ 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,push in 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)"
这是什么意思?
感谢。
答案 0 :(得分:13)
无论使用何种变体,该指令都称为MOV
。 l
后缀只是一个gcc / AT&amp; T汇编约定,用于指定所需操作数的大小,在本例中为4个字节的操作数。
在英特尔语法中 - 存在任何歧义 - 而不是为指令添加后缀通常用内容参数标记所需大小(例如BYTE
,WORD
,{{1等等,这只是实现同样事情的另一种方式。
DWORD
是89 55
从32位寄存器MOV
到32位寄存器EBP
的正确字节序列。两个列表都没有错。
指定生成此汇编代码的文件:
ESP
表示.file "test.c"
是一个全局符号(带有外部链接的C变量):
accum
以下字节应放在 .globl accum
部分中,这是一个在目标文件中不占用空间但在运行时分配和归零的部分。
bss
在4字节边界上对齐:
.bss
这是一个对象(一个变量,而不是一些代码):
.align 4
这是四个字节:
.type accum, @object
这里定义了 .size accum, 4
,四个零字节。
accum
现在从 accum:
.zero 4
部分切换到通常存储功能的文本部分。
bss
添加最多三个字节的填充以确保我们处于4字节(2 ^ 2)边界:
.text
.p2align 2,,3
是一个全局符号,它是一个函数。
sum
.globl sum
.type sum, @function
的尺寸为“此处” - “main
开始的地方”:
main
指定gcc特定堆栈选项的位置。通常,您可以选择使用可执行堆栈(不是非常安全)或不使用(通常是首选)。
.size main, .-main
确定编译器生成此程序集的版本:
.section .note.GNU-stack,"",@progbits
答案 1 :(得分:0)
汇编程序列表和反汇编程序列表显示相同的代码,但使用不同的语法。附加的-l是gcc使用的语法变体。你在工具中有不同的语法(C编译器输出和反汇编程序)显示你的工具链的弱点。
在sum中偏移量为11的反汇编:显示了一些垃圾字节。下一个函数main的入口点是4字节对齐的,它给出了这个间隙,填充了垃圾。
一堆.statements由汇编程序的文档定义。通常他们不提供任何可执行代码。