我在Richard Blum的专业汇编语言一书中找到了这个文本。
编译步骤转换文本编程语言语句 进入执行申请所需的指令代码 功能。每个HLL代码行都与一个或多个匹配 更多与特定处理器有关的指令代码 应用程序将运行。例如,简单的HLL代码
int main() { int i = 1; exit(0); }
编译为以下IA-32指令代码:
55 89 E5 83 EC 08 C7 45 FC 01 00 00 00 83 EC 0C 6A 00 E8 D1 FE FF FF
但是当我自己尝试这个程序时,我无法重现这些结果。
首先是关于我的系统和编译器的一些细节。
$ cat /etc/debian_version
8.3
$ uname -a
Linux debian1 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u2 (2016-01-02) x86_64 GNU/Linux
$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ dpkg -l gcc-multilib
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=========================================-=========================-=========================-========================================================================================
ii gcc-multilib 4:4.9.2-2 amd64 GNU C compiler (multilib files)
这是我写的程序。
$ cat foo.c
#include <stdlib.h>
int main()
{
int i = 1;
exit(0);
}
以下是仅在编译后得到的结果。
$ gcc -m32 -c foo.c
$ objdump -d foo.o
foo.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 8d 4c 24 04 lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xfffffff0,%esp
7: ff 71 fc pushl -0x4(%ecx)
a: 55 push %ebp
b: 89 e5 mov %esp,%ebp
d: 51 push %ecx
e: 83 ec 14 sub $0x14,%esp
11: c7 45 f4 01 00 00 00 movl $0x1,-0xc(%ebp)
18: 83 ec 0c sub $0xc,%esp
1b: 6a 00 push $0x0
1d: e8 fc ff ff ff call 1e <main+0x1e>
以下是我在编译和链接后得到的结果。
$ gcc -c foo.c
$ objdump -d a.out | grep -A15 "<main>"
080483fb <main>:
80483fb: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483ff: 83 e4 f0 and $0xfffffff0,%esp
8048402: ff 71 fc pushl -0x4(%ecx)
8048405: 55 push %ebp
8048406: 89 e5 mov %esp,%ebp
8048408: 51 push %ecx
8048409: 83 ec 14 sub $0x14,%esp
804840c: c7 45 f4 01 00 00 00 movl $0x1,-0xc(%ebp)
8048413: 83 ec 0c sub $0xc,%esp
8048416: 6a 00 push $0x0
8048418: e8 c3 fe ff ff call 80482e0 <exit@plt>
804841d: 66 90 xchg %ax,%ax
804841f: 90 nop
08048420 <__libc_csu_init>:
如何重现作者在书中提供的结果?
答案 0 :(得分:4)
书中没有的额外说明是:
80483fb: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483ff: 83 e4 f0 and $0xfffffff0,%esp
8048402: ff 71 fc pushl -0x4(%ecx)
8048408: 51 push %ecx
8048409: 83 ec 14 sub $0x14,%esp
...
804841d: 66 90 xchg ax,ax
804841f: 90 nop
第一对线将堆栈对齐到16字节边界。这样可以提高性能(参数不能跨越缓存行边界)并允许使用仅在16位对齐地址上运行的SIMD指令。
最后的xchg %ax, %ax
是一个2字节的NOP。 nop的3个字节无关紧要,因为它们无论如何都无法访问。它们用于将__libc_csu_init
函数填充到合适的对齐位置。
至于装配的不同之处,装配是一种编程语言,通常有多种方法可以做。您不能指望C程序在编译器,相同编译器的版本或相同版本的配置之间提供相同的输出。
在您的特定情况下,16位堆栈对齐归因于-mpreferred-stack-boundary=4
和归因于-falign-functions
的3字节nop
。
当您调用gcc
时,这些参数被配置为默认参数。直接或-O2
或类似的要求。