Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.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
使用GCC生成可读的程序集?_C_Gcc_Assembly - Fatal编程技术网

使用GCC生成可读的程序集?

使用GCC生成可读的程序集?,c,gcc,assembly,C,Gcc,Assembly,我想知道如何使用我的C源文件来转储机器代码的助记符版本,这样我就可以看到我的代码被编译成了什么。您可以用Java实现这一点,但我还没有找到使用GCC的方法 我正试图在汇编中重新编写一个C方法,看看GCC是如何做的,这将是一个很大的帮助 使用-S(注意:大写字母S)开关切换到GCC,它将向扩展名为.S的文件发出汇编代码。例如,以下命令: gcc-O2-sfoo.c 将生成的程序集代码保留在文件foo.s上 直接从(但删除错误的-c使用-S(注意:大写字母S)开关切换到GCC,它将向扩展名为.S的文

我想知道如何使用我的C源文件来转储机器代码的助记符版本,这样我就可以看到我的代码被编译成了什么。您可以用Java实现这一点,但我还没有找到使用GCC的方法

我正试图在汇编中重新编写一个C方法,看看GCC是如何做的,这将是一个很大的帮助

使用-S(注意:大写字母S)开关切换到GCC,它将向扩展名为.S的文件发出汇编代码。例如,以下命令:

gcc-O2-sfoo.c

将生成的程序集代码保留在文件foo.s上

直接从(但删除错误的
-c

使用-S(注意:大写字母S)开关切换到GCC,它将向扩展名为.S的文件发送程序集代码。例如,以下命令:


gcc-O2-S-cfoo.c

如果使用调试符号编译,则可以使用
objdump
生成更可读的反汇编

>objdump --help
[...]
-S, --source             Intermix source code with disassembly
-l, --line-numbers       Include line numbers and filenames in output
objdump-drwC-Mintel
很好:

  • -r
    在重新定位时显示符号名称(因此您可以在下面的
    调用
    说明中看到
    放置
  • -R
    显示动态链接重定位/符号名称(对共享库有用)
  • 代码> -c/代码> DEM+C++符号名称< /LI>
  • -w
    是“宽”模式:它不换行机器代码字节
  • -Mintel
    :像
    一样使用GAS/binutils MASM。英特尔语法noprefix
    语法,而不是AT&T
  • -S
    :使用反汇编交错源代码行
您可以在
~/.bashrc


例如:

> gcc -g -c test.c
> objdump -d -M intel -S test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main(void)
{
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   83 e4 f0                and    esp,0xfffffff0
   6:   83 ec 10                sub    esp,0x10
    puts("test");
   9:   c7 04 24 00 00 00 00    mov    DWORD PTR [esp],0x0
  10:   e8 fc ff ff ff          call   11 <main+0x11>

    return 0;
  15:   b8 00 00 00 00          mov    eax,0x0
}
  1a:   c9                      leave  
  1b:   c3                      ret
gcc-g-c test.c >objdump-d-M intel-S test.o test.o:文件格式elf32-i386 第节的分解。正文: 00000000 : #包括 内部主(空) { 0:55推ebp 1:89 e5 mov ebp,esp 3:83 e4 f0和esp,0xfffffff0 6:83 ec 10子esp,0x10 看跌期权(“测试”); 9:c7 04 24 00 mov DWORD PTR[esp],0x0 10:e8 fc ff呼叫11 返回0; 15:B800 mov eax,0x0 } 1a:c9离开 1b:c3 ret
请注意,这并没有使用
-r
,因此
调用rel32=-4
没有使用
put
符号名称进行注释。并且看起来像一个中断的
调用
,它跳转到main中调用指令的中间。请记住,调用编码中的
rel32
位移只是一个占位符,直到链接器填充一个实际的偏移量(在这种情况下是到PLT存根,除非您静态链接libc)。

如果您给出标志
-fverbose asm
,它将

在生成的汇编代码中添加额外的注释信息,使其更具可读性

[…]增加的评论包括:

  • 有关编译器版本和命令行选项的信息
  • 与汇编指令关联的源代码行,格式为FILENAME:LINENUMBER:CONTENT OF LINE
  • 高级表达式对应于各种汇编指令操作数的提示

默认情况下,在基于x86的系统上使用
-S
开关切换到GCC会产生AT&T语法转储,这可以通过
-masm=att
开关指定,如下所示:

gcc-S-masm=att code.c
然而,如果您想以英特尔语法生成转储,可以使用
-masm=Intel
开关,如下所示:

gcc-S-masm=intel code.c (两者都将
code.c
转储到各自的语法中,分别转储到文件
code.s

为了使用objdump产生类似的效果,您需要使用
--反汇编程序选项=
intel
/
att
开关,例如(使用代码转储来说明语法上的差异):

$objdump-d——反汇编程序选项=att code.c
080483c4:
80483c4:8d 4c 24 04 lea 0x4(%esp),%ecx
80483c8:83 e4 f0和$0xfffffff0,%esp
80483cb:ff 71 fc PUSH-0x4(%ecx)
80483ce:55推力%ebp
80483cf:89 e5 mov%esp,%ebp
80483d1:51推力%ecx
80483d2:83 ec 04子$0x4,%esp
80483d5:c7 04 24 b0 84 04 08 movl$0x80484b0,(%esp)
80483dc:e8 13 ff ff ff呼叫80482f4
80483e1:b8 00 mov$0x0,%eax
80483e6:83 c4 04添加$0x4,%esp
80483e9:59 pop%ecx
80483ea:5d pop%ebp
80483eb:8D61 fc lea-0x4(%ecx),%esp
80483ee:c3 ret
80483ef:90 nop

$objdump-d--反汇编程序选项=英特尔代码.c
080483c4:
80483c4:8d 4c 24 04 lea ecx[esp+0x4]
80483c8:83 e4 f0和esp,0xfffffff0
80483cb:ff 71 fc推送DWORD PTR[ecx-0x4]
80483ce:55推式ebp
80483cf:89 e5 mov ebp,esp
80483d1:51推式ecx
80483d2:83 ec 04子esp,0x4
80483d5:c7 04 24 b0 84 04 08 mov DWORD PTR[esp],0x80484b0
80483dc:e8 13 ff ff ff呼叫80482f4
80483e1:B800 mov eax,0x0
80483e6:83 c4 04添加esp,0x4
80483e9:59波普ecx
80483ea:5d pop ebp
80483eb:8d 61 fc lea esp,[ecx-0x4]
80483ee:c3 ret
80483ef:90 nop

您可以将gdb用于类似objdump的对象

这段摘录是德 (gdb) disas /m main Dump of assembler code for function main: 5 { 0x08048330 : push %ebp 0x08048331 : mov %esp,%ebp 0x08048333 : sub $0x8,%esp 0x08048336 : and $0xfffffff0,%esp 0x08048339 : sub $0x10,%esp 6 printf ("Hello.\n"); 0x0804833c : movl $0x8048440,(%esp) 0x08048343 : call 0x8048284 7 return 0; 8 } 0x08048348 : mov $0x0,%eax 0x0804834d : leave 0x0804834e : ret End of assembler dump.
#include <stdio.h>

void func()
{
  printf( "hello world\n" ) ;
}
-x c -std=c99 -O3