使用GCC生成可读的程序集?
我想知道如何使用我的C源文件来转储机器代码的助记符版本,这样我就可以看到我的代码被编译成了什么。您可以用Java实现这一点,但我还没有找到使用GCC的方法 我正试图在汇编中重新编写一个C方法,看看GCC是如何做的,这将是一个很大的帮助 使用-S(注意:大写字母S)开关切换到GCC,它将向扩展名为.S的文件发出汇编代码。例如,以下命令:使用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的文
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