Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么为我的C程序生成的机器代码与书中给出的不同?_C_Gcc_Assembly_X86 - Fatal编程技术网

为什么为我的C程序生成的机器代码与书中给出的不同?

为什么为我的C程序生成的机器代码与书中给出的不同?,c,gcc,assembly,x86,C,Gcc,Assembly,X86,我在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

我在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>:

如何复制书中作者提供的结果?

书中没有的额外说明包括:

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位堆栈对齐是由于,3字节nop是由于


当您调用gcc时,这些参数被配置为默认参数。可以直接使用,也可以根据-O2或类似要求使用。

使用具有完全相同标志的完全相同的编译器版本。因为有很多方法可以从C生成asm代码,所以通常不能期望所有编译器都有相同的输出。你的书真的没有列出该机器代码的反汇编吗?这有点奇怪。请注意,-mprefered stack boundary=4或更高现在是。另外,gcc和clang确实可以从main中省略这些内容,因为CRT启动代码在Linux启动进程并对齐堆栈16B之后保持堆栈对齐。但是是的,NOP的3个字节只是在下一个函数之前填充,而不是当前函数的一部分。它在调用noreturn函数出口处结束。我想知道为什么它费心调用noreturn函数,而不是无条件地跳转到它。“有什么明显的我遗漏了吗,@peter?@CodyGray:IDK为什么尾部调用优化没有发生。”。我也在想同样的事情。我不认为我们都遗漏了什么明显的东西。我的意思是,如果函数返回,它就会崩溃,exit3保证函数不会失败。我猜gcc没有对noreturn函数使用jmp的窥视孔优化,因为这意味着异常的堆栈帧。哦,对了,call会推送一个返回地址,所以exit会在上面查找它的arg。gcc可能已发出mov$0,4%esp/jmpexit@plt,但这是一个更奇怪的窥视孔和更糟糕的代码大小