Używanie GCC do tworzenia czytelnego montażu?

Zastanawiałem się, jak użyć GCC na moim pliku źródłowym C, aby zrzucić mnemoniczną wersję kodu maszynowego, aby zobaczyć, w co jest kompilowany mój kod. Możesz to zrobić z Javą, ale nie byłem w stanie znaleźć sposobu z GCC.

Próbuję ponownie napisać metodę C w assembly i widząc, jak robi to GCC, byłoby to bardzo pomocne.

 211
Author: Ryan Tenney, 2009-08-17

9 answers

Jeśli kompilujesz z symbolami debugowania, możesz użyć objdump, aby stworzyć bardziej czytelny demontaż.

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

objdump -drwC -Mintel jest ładny:

  • -r pokazuje nazwy symboli na relokacjach (więc zobaczysz puts w instrukcji call poniżej)
  • -R pokazuje dynamicznie łączące relokacje / nazwy symboli (przydatne w bibliotekach współdzielonych)
  • -C demangles C++ nazwy symboli
  • Jest to tryb "szeroki", który nie zawija bajtów kodu maszynowego.]}
  • -Mintel: użyj GAS / binutils MASM-like .intel_syntax noprefix składnia zamiast AT & T
  • -S: przeplatać linie źródłowe z demontażem.

Możesz umieścić coś takiego alias disas="objdump -drwCS -Mintel" w swoim ~/.bashrc


Przykład:

> 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
 284
Author: Bastien Léonard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-02 01:20:13

Chciałbym dodać do tych odpowiedzi, że jeśli podasz GCC flagę -fverbose-asm, asembler, który emituje, będzie dużo jaśniejszy do odczytania.

 86
Author: kmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-30 22:42:37

Użyj przełącznika-S (Uwaga: duże S) na GCC, a to spowoduje wysłanie kodu asemblera do pliku z .rozszerzenie S. Na przykład następujące polecenie:

gcc -O2 -S foo.c

Pozostawi wygenerowany kod złożenia w pliku foo.s.

Wyrwane prosto z http://www.delorie.com/djgpp/v2faq/faq8_20.html (ale usunięcie błędnych -c)

 69
Author: Andrew Keeton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-18 21:26:44

Użycie przełącznika -S do GCC w systemach opartych na x86 powoduje domyślnie zrzut składni AT & T, który może być określony za pomocą przełącznika -masm=att, Tak:

gcc -S -masm=att code.c

Natomiast jeśli chcesz stworzyć zrzut w składni Intela, możesz użyć przełącznika -masm=intel w następujący sposób:

gcc -S -masm=intel code.c

(oba wytwarzają zrzuty code.c do różnych składni, odpowiednio do pliku code.s)

Aby uzyskać podobne efekty z objdump, powinieneś użyć --disassembler-options= intel/att switch, przykład (z zrzutami kodu, aby zilustrować różnice w składni):

 $ objdump -d --disassembler-options=att code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    0x4(%esp),%ecx
 80483c8:   83 e4 f0                and    $0xfffffff0,%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    $0x4,%esp
 80483d5:   c7 04 24 b0 84 04 08    movl   $0x80484b0,(%esp)
 80483dc:   e8 13 ff ff ff          call   80482f4 <puts@plt>
 80483e1:   b8 00 00 00 00          mov    $0x0,%eax
 80483e6:   83 c4 04                add    $0x4,%esp 
 80483e9:   59                      pop    %ecx
 80483ea:   5d                      pop    %ebp
 80483eb:   8d 61 fc                lea    -0x4(%ecx),%esp
 80483ee:   c3                      ret
 80483ef:   90                      nop

I

$ 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
 47
Author: amaterasu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-01 16:26:23

Godbolt jest bardzo użytecznym narzędziem, lista zawiera tylko kompilatory C++, ale możesz użyć flagi -x c, aby traktować kod jako C. Następnie wygeneruje listę zestawów dla Twojego kodu obok siebie i możesz użyć opcji Colourise, aby wygenerować kolorowe paski, aby wizualnie wskazać, który kod źródłowy mapuje do wygenerowanego zestawu. Na przykład następujący kod:

#include <stdio.h>

void func()
{
  printf( "hello world\n" ) ;
}

Używając następującego wiersza poleceń:

-x c -std=c99 -O3

I Colourise wygenerowałyby po:

Tutaj wpisz opis obrazka

 33
Author: Shafik Yaghmour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-21 17:03:24

Czy próbowałeś gcc -S -fverbose-asm -O source.c i zajrzałeś do wygenerowanego source.s Pliku asemblera ?

Wygenerowany kod asemblera wchodzi do source.s (można go zastąpić za pomocą -o asembler-filename ); opcja -fverbose-asm prosi kompilator o wysłanie uwag asemblera "wyjaśniających" wygenerowany kod asemblera. Opcja -O prosi kompilator o bitową optymalizację (może zoptymalizować więcej za pomocą -O2 lub -O3).

Jeśli chcesz zrozumieć co robi gcc spróbuj przejść -fdump-tree-all ale bądź ostrożnie: dostaniesz setki plików zrzutu.

BTW, GCC jest rozszerzalny poprzez wtyczki lub z MELT (język specyficzny dla domeny wysokiego poziomu do rozszerzenia GCC).

 19
Author: Basile Starynkevitch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-30 23:29:58

Możesz użyć gdb do tego, jak objdump.

Ten fragment pochodzi z http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64


Oto przykład pokazujący mixed source+assembly dla Intel x86:

  (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.
 17
Author: Vishal Sagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-15 11:18:06

Użyj przełącznika-S (Uwaga: duże S) na GCC, a to spowoduje wysłanie kodu asemblera do pliku z .rozszerzenie S. Na przykład następujące polecenie:

Gcc-O2-S-C foo.c

 12
Author: codymanix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-17 19:24:42

Nie dałem szans gcc, ale w przypadku g++. Poniższe polecenie działa dla mnie. -g for debug build and-Wa, - adhln is passed to assembler for listing with source code

G++-G-Wa, - adhln src.cpp

 4
Author: DAG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 06:00:56