Использование GCC для создания читаемой сборки?
Мне было интересно, как использовать GCC в моем исходном файле C, чтобы сбросить мнемоническую версию машинного кода, чтобы я мог видеть, в что мой код компилируется. Вы можете сделать это с Java, но я не смог найти способ с GCC.
Я пытаюсь переписать метод C в сборке и посмотреть, как GCC делает это, было бы большой помощью.
9 ответов
если вы компилируете с символами отладки, вы можете использовать objdump
произвести более читаемую разборку.
>objdump --help
[...]
-S, --source Intermix source code with disassembly
-l, --line-numbers Include line numbers and filenames in output
objdump -drwC -Mintel
хорошо:
-
-r
показывает имена символов при перемещениях (так что вы увидитеputs
наcall
инструкцию ниже) -
-R
показывает динамическое связывание перемещений / имен символов (полезно в общих библиотеках) -
-C
имена символов demangles C++ -
-w
" широкий " режим: это не линия-обернуть машина-кода байт -
-Mintel
: используйте газ / binutils MASM-like.intel_syntax noprefix
синтаксис вместо AT & T -
-S
: чередование исходных линий с разборкой.
вы могли бы поставить что-то вроде alias disas="objdump -drwCS -Mintel"
в своем ~/.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 флаг -fverbose-asm
, ассемблер, который он испускает, будет намного яснее читать.
используйте переключатель-S (Примечание: capital S) в GCC, и он выдаст код сборки в файл с a .расширение С. Например, следующая команда:
gcc -O2 -S foo.c
оставит сгенерированный код сборки в файле foo.s.
вырвано прямо из http://www.delorie.com/djgpp/v2faq/faq8_20.html (но удаление ошибочных -c
)
С помощью -S
переключение на GCC в системах на базе x86 создает дамп синтаксиса AT&T по умолчанию, который может быть указан с помощью -masm=att
переключатель, вот так:
gcc -S -masm=att code.c
тогда как если вы хотите создать дамп в синтаксисе Intel, вы можете использовать -masm=intel
переключатель, вот так:
gcc -S -masm=intel code.c
(оба производят свалки code.c
в их различный синтаксис, в файл code.s
соответственно)
для того чтобы произвести подобные влияния с objdump, вы хотите использовать --disassembler-options=
intel
/att
switch, пример (с дампами кода для иллюстрации различий в синтаксисе):
$ objdump -d --disassembler-options=att code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483c8: 83 e4 f0 and xfffffff0,%esp
80483cb: ff 71 fc pushl -0x4(%ecx)
80483ce: 55 push %ebp
80483cf: 89 e5 mov %esp,%ebp
80483d1: 51 push %ecx
80483d2: 83 ec 04 sub x4,%esp
80483d5: c7 04 24 b0 84 04 08 movl x80484b0,(%esp)
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov x0,%eax
80483e6: 83 c4 04 add x4,%esp
80483e9: 59 pop %ecx
80483ea: 5d pop %ebp
80483eb: 8d 61 fc lea -0x4(%ecx),%esp
80483ee: c3 ret
80483ef: 90 nop
и
$ objdump -d --disassembler-options=intel code.c
080483c4 <main>:
80483c4: 8d 4c 24 04 lea ecx,[esp+0x4]
80483c8: 83 e4 f0 and esp,0xfffffff0
80483cb: ff 71 fc push DWORD PTR [ecx-0x4]
80483ce: 55 push ebp
80483cf: 89 e5 mov ebp,esp
80483d1: 51 push ecx
80483d2: 83 ec 04 sub esp,0x4
80483d5: c7 04 24 b0 84 04 08 mov DWORD PTR [esp],0x80484b0
80483dc: e8 13 ff ff ff call 80482f4 <puts@plt>
80483e1: b8 00 00 00 00 mov eax,0x0
80483e6: 83 c4 04 add esp,0x4
80483e9: 59 pop ecx
80483ea: 5d pop ebp
80483eb: 8d 61 fc lea esp,[ecx-0x4]
80483ee: c3 ret
80483ef: 90 nop
godbolt - очень полезный инструмент, в их списке есть только компиляторы C++, но вы можете использовать -x c
флаг, чтобы получить его рассматривать код как C. Затем он будет генерировать список сборок для вашего кода бок о бок, и вы можете использовать Colourise
возможность генерировать цветные полосы, чтобы визуально указать, какой исходный код сопоставляется с сгенерированной сборкой. Например, следующий код:
#include <stdio.h>
void func()
{
printf( "hello world\n" ) ;
}
используя следующую командную строку:
-x c -std=c99 -O3
и Colourise
будет генерировать следующее:
ты gcc -S -fverbose-asm -O source.c
затем посмотрите в сгенерированный source.s
файл ассемблер ?
сгенерированный код ассемблера переходит в source.s
(вы можете переопределить это с помощью -o
ассемблер-имя файла ); the -fverbose-asm
опция просит компилятор выдать некоторые комментарии ассемблера, "объясняющие" сгенерированный код ассемблера. The -O
опция просит компилятор немного оптимизировать (он может оптимизировать больше с помощью -O2
или -O3
).
если вы хотите понять что?!--8--> делает попытку передает -fdump-tree-all
но будьте осторожны: вы получите сотни файлов дампа.
кстати, GCC является расширяемым через плагины или с расплавить (язык домена высокого уровня для расширения GCC).
вы можете использовать gdb для этого, как objdump.
этот отрывок взят из http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64
вот пример, показывающий смешанный источник + сборка для Intel x86:
(gdb) disas /m main Dump of assembler code for function main: 5 { 0x08048330 : push %ebp 0x08048331 : mov %esp,%ebp 0x08048333 : sub x8,%esp 0x08048336 : and xfffffff0,%esp 0x08048339 : sub x10,%esp 6 printf ("Hello.\n"); 0x0804833c : movl x8048440,(%esp) 0x08048343 : call 0x8048284 7 return 0; 8 } 0x08048348 : mov x0,%eax 0x0804834d : leave 0x0804834e : ret End of assembler dump.
используйте переключатель-S (Примечание: capital S) в GCC, и он выдаст код сборки в файл с a .расширение С. Например, следующая команда:
ССЗ -О2 -с -с ФОО.c
Я не дал выстрел в gcc, но в случае g++. Команда ниже работает для меня. - g для сборки отладки и-Wa, - adhln передается ассемблеру для листинга с исходным кодом
g++ - g-Wa, - adhln src.cpp