Verwenden Sie GCC, um eine lesbare Baugruppe zu erstellen?

Lesezeit: 10 Minuten

Benutzeravatar von James
James

Ich habe mich gefragt, wie man es benutzt GCC in meiner C-Quelldatei, um eine mnemonische Version des Maschinencodes auszugeben, damit ich sehen konnte, in was mein Code kompiliert wurde. Sie können dies mit Java tun, aber ich konnte mit GCC keinen Weg finden.

Ich versuche, eine C-Methode in Assembly neu zu schreiben, und zu sehen, wie GCC dies tut, wäre eine große Hilfe.

  • Beachten Sie, dass „Bytecode“ normalerweise den Code bezeichnet, der von einer VM wie JVM oder der CLR von .NET verwendet wird. Die Ausgabe von GCC wird besser als “Maschinencode”, “Maschinensprache” oder “Assemblersprache” bezeichnet.

    – Javier

    17. August 2009 um 19:27 Uhr

  • Ich habe eine Antwort mit Godbolt hinzugefügt, da es ein sehr leistungsfähiges Tool ist, um schnell damit zu experimentieren, wie sich verschiedene Optionen auf Ihre Codegenerierung auswirken.

    – Shafik Yaghmour

    12. September 2014 um 2:35 Uhr

  • stackoverflow.com/a/19083877/995714

    – phuklv

    30. November 2014 um 6:33 Uhr

  • Weitere Tipps, wie Sie die Ausgabe von asm für Menschen lesbar machen, finden Sie unter: Wie entferne ich „Rauschen“ aus der Ausgabe der GCC/Clang-Assembly?

    – Peter Cordes

    5. September 2016 um 20:46 Uhr

  • Hier beantwortet: stackoverflow.com/questions/137038/… Verwenden Sie die Option -S für gcc (oder g++).

    – wissen ist Macht

    26. Juli 2017 um 19:38 Uhr

Benutzeravatar von Bastien Léonard
Bastien Leonard

Wenn Sie mit Debug-Symbolen (add -g zu Ihrer GCC-Befehlszeile, auch wenn Sie es auch verwenden -O31), können Sie verwenden objdump -S um eine besser lesbare Disassemblierung zu erzeugen, die mit C-Quelle verschachtelt ist.

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

objdump -drwC -Mintel ist schön:

  • -r zeigt Symbolnamen bei Umzügen (so würden Sie sehen puts in dem call Anleitung unten)
  • -R zeigt dynamische Verlinkungen / Symbolnamen (nützlich für gemeinsam genutzte Bibliotheken)
  • -C demangles C++ Symbolnamen
  • -w ist der “Wide”-Modus: Die Maschinencode-Bytes werden nicht umgebrochen
  • -Mintel: Verwenden Sie GAS/binutils MASM-ähnlich .intel_syntax noprefix Syntax statt AT&T
  • -S: Quellzeilen mit Disassemblierung verschachteln.

Sie könnten so etwas wie setzen alias disas="objdump -drwCS -Mintel" in deiner ~/.bashrc. Wenn nicht auf x86 oder wenn Sie die AT&T-Syntax mögen, lassen Sie es weg -Mintel.


Beispiel:

> 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

Beachten Sie, dass dies ist nicht verwenden -r also die call rel32=-4 ist nicht mit kommentiert puts Symbolname. Und sieht aus wie kaputt call das springt in die Mitte des Aufrufbefehls in main. Denken Sie daran, dass die rel32 Die Verschiebung in der Aufrufcodierung ist nur ein Platzhalter, bis der Linker einen echten Offset ausfüllt (in diesem Fall zu einem PLT-Stub, es sei denn, Sie verknüpfen libc statisch).


Fußnote 1: Interleaving-Quelle kann unordentlich und in optimierten Builds nicht sehr hilfreich sein; dafür überlegen https://godbolt.org/ oder andere Möglichkeiten, um zu visualisieren, welche Anweisungen zu welchen Quellzeilen gehören. In optimiertem Code gibt es nicht immer eine einzelne Quellzeile, die eine Anweisung berücksichtigt, aber die Debug-Informationen wählen eine Quellzeile für jede asm-Anweisung aus.

  • Gibt es einen Schalter, um nur die Intel-Anweisungen abzurufen?

    – James

    17. August 2009 um 19:39 Uhr

  • All dies sind Intel-Anweisungen, da sie auf Intel-Prozessoren ausgeführt werden: D.

    – ganz

    18. August 2009 um 4:01 Uhr

  • @toto Ich denke, er meint Intel-Syntax anstelle von AT & T-Syntax

    – Amok

    9. Oktober 2009 um 21:56 Uhr

  • Auf die zwischengeschaltete Objektdatei kann mit der Schalterfolge verzichtet werden -Wa,-adhln -g to gcc. Dies setzt voraus, dass der Assembler Gas ist, und dies muss nicht immer der Fall sein.

    – Marc Butler

    8. September 2010 um 16:45 Uhr


  • @ James Ja, Versorgung -Mintel.

    – fuz

    26. September 2015 um 15:42 Uhr

Kaspers Benutzer-Avatar
Kasper

Wenn du gibst GCC die Flagge -fverbose-asmes wird

Fügen Sie zusätzliche Kommentarinformationen in den generierten Assemblycode ein, um ihn besser lesbar zu machen.

[…] Zu den hinzugefügten Kommentaren gehören:

  • Informationen zur Compilerversion und Kommandozeilenoptionen,
  • die den Assembleranweisungen zugeordneten Quellcodezeilen in der Form FILENAME:LINENUMBER:CONTENT OF LINE,
  • Hinweise darauf, welche High-Level-Ausdrücke den verschiedenen Assemblerbefehlsoperanden entsprechen.

  • Aber dann würde ich alle Schalter verloren, für die ich gebraucht habe objdumpobjdump -drwCS -Mintelalso wie kann ich so etwas verwenden verbose mit objdump? Damit ich auch Kommentare im asm-Code haben kann -fverbose-asm im gcc?

    – Hirte

    10. Januar 2020 um 17:08 Uhr


  • @Herdsman: Das kannst du nicht. Das zusätzliche Zeug -fverbose-asm fügt hinzu, hat die Form von Kommentaren in der asm-Syntax der Ausgabe, nicht von Direktiven, die etwas Zusätzliches in die einfügen .o Datei. Es wird alles zur Montagezeit verworfen. Sehen Sie sich die Ausgabe des Compilers asm an stattdessen der Demontage, zB auf godbolt.org wo Sie es einfach mit der Quellzeile per Mouseover und farblicher Hervorhebung der entsprechenden Quell- / ASM-Zeilen abgleichen können. Wie entferne ich “Rauschen” aus der GCC/Clang-Assembly-Ausgabe?

    – Peter Cordes

    9. Mai 2020 um 19:16 Uhr


Benutzeravatar von Andrew Keeton
Andreas Keeton

Verwenden Sie den Schalter -S (Anmerkung: großes S) für GCC, und der Assemblercode wird in eine Datei mit der Erweiterung .s ausgegeben. Beispielsweise der folgende Befehl:

gcc -O2 -S foo.c

belässt den generierten Assembler-Code in der Datei foo.s.

Direkt abgerissen http://www.delorie.com/djgpp/v2faq/faq8_20.html (aber fehlerhaft entfernen -c)

  • Sie sollten -c und -S nicht mischen, sondern nur eines davon verwenden. In diesem Fall überschreibt das eine das andere, wahrscheinlich abhängig von der Reihenfolge, in der sie verwendet werden.

    – Adam Rosenfield

    17. August 2009 um 19:28 Uhr

  • @AdamRosenfield Gibt es einen Hinweis darauf, dass -c und -S nicht gemischt werden sollten? Wenn es wahr ist, sollten wir den Autor möglicherweise daran erinnern und es bearbeiten.

    – Toni

    5. August 2014 um 11:55 Uhr

  • @ Toni: gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options “Sie können … eines der Optionen -c, -S oder -E, um anzugeben, wo gcc aufhören soll.”

    – Nate Eldredge

    10. April 2016 um 0:32 Uhr

  • Wenn Sie alle Zwischenausgänge wünschen, verwenden Sie gcc -march=native -O3 -save-temps. Sie können immer noch verwenden -c bei der Erstellung von Objektdateien anzuhalten, ohne zu versuchen, eine Verknüpfung herzustellen, oder was auch immer.

    – Peter Cordes

    2. Juni 2018 um 1:21 Uhr


  • -save-temps ist interessant, da es auf einen Schlag den genauen generierten Code ausgibt, während die andere Option den Compiler mit aufruft -S bedeutet zweimal kompilieren und möglicherweise mit unterschiedlichen Optionen. Aber -save-temps speichert alles im aktuellen Verzeichnis, was ziemlich chaotisch ist. Sieht so aus, als wäre es eher als Debug-Option für GCC gedacht als als Werkzeug zur Überprüfung Ihres Codes.

    – Stéphane Gourichon

    22. Januar 2020 um 18:16 Uhr

Benutzeravatar von amaterasu
amaterasu

Verwendung der -S Der Wechsel zu GCC auf x86-basierten Systemen erzeugt standardmäßig einen Dump der AT&T-Syntax, die mit angegeben werden kann -masm=att schalten, so:

gcc -S -masm=att code.c

Wenn Sie hingegen einen Dump in Intel-Syntax erstellen möchten, können Sie die verwenden -masm=intel schalten, so:

gcc -S -masm=intel code.c

(Beide produzieren Dumps von code.c in ihre verschiedene Syntax, in die Datei code.s beziehungsweise)

Um ähnliche Effekte mit objdump zu erzeugen, sollten Sie die verwenden --disassembler-options= intel/att switch, ein Beispiel (mit Code-Dumps zur Veranschaulichung der Unterschiede in der Syntax):

 $ 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

und

$ 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

Benutzeravatar von Shafik Yaghmour
Shafik Yaghmur

Gottriegel ist ein sehr nützliches Tool, das nur C++-Compiler auflistet, die Sie verwenden können -x c Flag, damit es den Code als C behandelt. Es wird dann nebeneinander eine Assemblyliste für Ihren Code generiert, und Sie können die verwenden Colourise Option zum Generieren farbiger Balken, um visuell anzuzeigen, welcher Quellcode der generierten Assembly zugeordnet ist. Zum Beispiel der folgende Code:

#include <stdio.h>

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

mit der folgenden Befehlszeile:

-x c -std=c99 -O3

und Colourise würde folgendes erzeugen:

Geben Sie hier die Bildbeschreibung ein

  • Es wäre schön zu wissen, wie Godbolt-Filter funktionieren: .LC0, .text, // und Intel. Intel ist einfach -masm=intel aber was ist mit dem Rest?

    – Z-Boson

    22. Februar 2017 um 8:01 Uhr


  • Ich denke, es wird hier erklärt: stackoverflow.com/a/38552509/2542702

    – Z-Boson

    22. Februar 2017 um 8:02 Uhr

  • Godbolt unterstützt C (zusammen mit einer Menge anderer Sprachen wie Rust, D, Pascal …). Es gibt nur viel weniger C-Compiler, also ist es immer noch besser, C++-Compiler zu verwenden -x c

    – phuklv

    27. April 2019 um 9:34 Uhr

  • Warum unterscheiden sich die Saiten zwischen der Quelle und der Baugruppe? Der Zeilenumbruch wurde am Ende entfernt

    – OmarL

    19. März 2021 um 10:38 Uhr

Hast du versucht gcc -S -fverbose-asm -O source.c Dann schauen Sie in die generierte source.s Assembler-Datei?

Der generierte Assembler-Code geht hinein source.s (Sie könnten das mit überschreiben -o Assembler-Dateiname ); das -fverbose-asm Option fordert den Compiler auf, einige Assembler-Kommentare auszugeben, die den generierten Assembler-Code “erklären”. Das -O Option fordert den Compiler auf, ein wenig zu optimieren (es könnte mehr optimieren mit -O2 oder -O3).

Wenn Sie was verstehen wollen gcc tut Versuch vorbei -fdump-tree-all aber seien Sie vorsichtig: Sie erhalten Hunderte von Dump-Dateien.

BTW, GCC ist durch erweiterbar Plugins oder mit SCHMELZEN (eine hochrangige domänenspezifische Sprache zur Erweiterung von GCC; die ich 2017 aufgegeben habe)

  • Es wäre schön zu wissen, wie Godbolt-Filter funktionieren: .LC0, .text, // und Intel. Intel ist einfach -masm=intel aber was ist mit dem Rest?

    – Z-Boson

    22. Februar 2017 um 8:01 Uhr


  • Ich denke, es wird hier erklärt: stackoverflow.com/a/38552509/2542702

    – Z-Boson

    22. Februar 2017 um 8:02 Uhr

  • Godbolt unterstützt C (zusammen mit einer Menge anderer Sprachen wie Rust, D, Pascal …). Es gibt nur viel weniger C-Compiler, also ist es immer noch besser, C++-Compiler zu verwenden -x c

    – phuklv

    27. April 2019 um 9:34 Uhr

  • Warum unterscheiden sich die Saiten zwischen der Quelle und der Baugruppe? Der Zeilenumbruch wurde am Ende entfernt

    – OmarL

    19. März 2021 um 10:38 Uhr

Benutzeravatar von agf
agf

Sie können gdb dafür wie objdump verwenden.

Dieser Auszug ist entnommen http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64


Hier ist ein Beispiel, das eine gemischte Quelle + Assemblierung für Intel x86 zeigt:

  (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.

1427020cookie-checkVerwenden Sie GCC, um eine lesbare Baugruppe zu erstellen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy