it-swarm.com.de

Verwenden Sie GCC, um lesbare Assemblys zu erstellen?

Ich habe mich gefragt, wie ich GCC in meiner C-Quelldatei verwende, um eine mnemonische Version des Maschinencodes zu sichern, damit ich sehen kann, in was mein Code kompiliert wird. 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 es wäre eine große Hilfe, zu sehen, wie GCC dies tut.

231
James

Wenn Sie mit Debug-Symbolen kompilieren, können Sie objdump verwenden, um eine besser lesbare Disassemblierung zu erzielen.

>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 an (daher wird puts in der Anweisung call unten angezeigt).
  • -R Zeigt dynamisch verknüpfte Verschiebungen/Symbolnamen (nützlich für gemeinsam genutzte Bibliotheken)
  • -C Verwirrt C++ - Symbolnamen
  • -w Ist der "Wide" -Modus: Die Maschinencode-Bytes werden nicht in Zeilenumbrüche eingeschlossen
  • -Mintel: Verwenden Sie die GAS/binutils MASM-ähnliche .intel_syntax noprefix - Syntax anstelle von AT & T
  • -S: Interleave Source Lines bei Disassemblierung.

Sie könnten etwas wie alias disas="objdump -drwCS -Mintel" In Ihren ~/.bashrc Einfügen.


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
312

Ich möchte zu diesen Antworten hinzufügen, dass, wenn Sie gcc die Flagge geben -fverbose-asm, der Assembler, den er ausgibt, ist viel klarer zu lesen.

95
kmm

Verwenden Sie den Schalter -S (Anmerkung: Großbuchstabe S) für GCC, und der Assemblycode wird in eine Datei mit der Erweiterung .s ausgegeben. Zum Beispiel der folgende Befehl:

gcc -O2 -S foo.c

der generierte Assembly-Code bleibt in der Datei foo.s.

Gerippt direkt von http://www.delorie.com/djgpp/v2faq/faq8_20.html (Entfernen von fehlerhaften -c)

73
Andrew Keeton

Verwendung der -S switch to GCC auf x86-basierten Systemen erzeugt standardmäßig einen Dump der AT & T-Syntax, der mit -masm=att wechseln, wie so:

gcc -S -masm=att code.c

Wenn Sie dagegen einen Speicherauszug in Intel-Syntax erstellen möchten, können Sie den Befehl -masm=intel wechseln, wie so:

gcc -S -masm=intel code.c

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

Um ähnliche Effekte mit objdump zu erzielen, sollten Sie das --disassembler-options=intel/att switch, ein Beispiel (mit Code-Dumps, um die Unterschiede in der Syntax zu veranschaulichen):

 $ 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 <[email protected]>
 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 <[email protected]>
 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
49
amaterasu

godbolt ist ein sehr nützliches Tool, sie listen nur C++ - Compiler auf, aber Sie können -x c flag, damit der Code als C behandelt wird. Anschließend wird eine Assembly-Liste für Ihren Code nebeneinander erstellt. Mit der Option Colourise können Sie farbige Balken erstellen, um visuell anzuzeigen, welcher Quellcode zugeordnet ist zur generierten Assembly. Zum Beispiel der folgende Code:

#include <stdio.h>

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

verwenden Sie die folgende Befehlszeile:

-x c -std=c99 -O3

und Colourise würde folgendes erzeugen:

enter image description here

34
Shafik Yaghmour

Haben Sie versucht gcc -S -fverbose-asm -O source.c Und dann in die erzeugte Assembler-Datei source.s Geschaut?

Der generierte Assembler-Code geht in source.s (Sie können dies mit -o Assembler-Dateiname überschreiben); Die Option -fverbose-asm fordert den Compiler auf, einige Assemblerkommentare auszugeben, die den generierten Assembler-Code "erläutern". Die Option -O Fordert den Compiler auf, ein wenig zu optimieren (es könnte mehr mit -O2 Oder -O3 Optimiert werden).

Wenn Sie verstehen möchten, was gcc tut, versuchen Sie, -fdump-tree-all Zu übergeben, aber seien Sie vorsichtig: Sie erhalten Hunderte von Dump-Dateien.

Übrigens ist GCC erweiterbar durch Plugins oder mit MELT (eine domänenspezifische Hochsprache zur Erweiterung von GCC; die ich 2017 aufgegeben habe )

22

Sie können dazu gdb wie objdump verwenden.

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


Hier ist ein Beispiel, das Mixed Source + Assembly für Intel x86 zeigt:

 (gdb) disas/m main 
 Speicherauszug des Assembler-Codes für die Funktion main: 
 5 {
 0x08048330:% ebp 
 0x08048331: mov % esp,% ebp 
 0x08048333: unter $ 0x8,% esp 
 0x08048336: und $ 0xfffffff0,% esp 
 0x08048339: unter $ 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 von Assembler Dump. 
19
Vishal Sagar

Verwenden Sie den Schalter -S (Anmerkung: Großbuchstabe S) für GCC, und der Assemblycode wird in eine Datei mit der Erweiterung .s ausgegeben. Zum Beispiel der folgende Befehl:

gcc -O & sub2; -S -c foo.c

13
codymanix

Ich habe gcc keine Chance gegeben, aber im Fall von g ++. Der folgende Befehl funktioniert für mich. -g für Debugbuild und -Wa, -adhln wird an Assembler zur Auflistung mit Quellcode übergeben

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

4
DAG