Wie kompiliere ich den von GCC generierten ASM?

74

Ich spiele mit ASM-Code herum und etwas stört mich.

Ich kompiliere das:

#include <stdio.h>

int main(int argc, char** argv){
  printf("Hello World\n");
  return 0;
}

mit gcc file.c -S -o file.Sdieser erzeugt ein schönes kleines Stück asm - Code:

    .cstring
LC0:
    .ascii "Hello World\0"
    .text
.globl _main
_main:
LFB3:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    subq    $16, %rsp
LCFI2:
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    leaq    LC0(%rip), %rdi
    call    _puts
    movl    $0, %eax
    leave
    ret
LFE3:
    .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
    .set L$set$0,LECIE1-LSCIE1
    .long L$set$0
LSCIE1:
    .long   0x0
    .byte   0x1
    .ascii "zR\0"
    .byte   0x1
    .byte   0x78
    .byte   0x10
    .byte   0x1
    .byte   0x10
    .byte   0xc
    .byte   0x7
    .byte   0x8
    .byte   0x90
    .byte   0x1
    .align 3
LECIE1:
.globl _main.eh
_main.eh:
LSFDE1:
    .set L$set$1,LEFDE1-LASFDE1
    .long L$set$1
LASFDE1:
    .long   LASFDE1-EH_frame1
    .quad   LFB3-.
    .set L$set$2,LFE3-LFB3
    .quad L$set$2
    .byte   0x0
    .byte   0x4
    .set L$set$3,LCFI0-LFB3
    .long L$set$3
    .byte   0xe
    .byte   0x10
    .byte   0x86
    .byte   0x2
    .byte   0x4
    .set L$set$4,LCFI1-LCFI0
    .long L$set$4
    .byte   0xd
    .byte   0x6
    .align 3
LEFDE1:
    .subsections_via_symbols

Mein nächstes Problem ist wirklich, wie kompiliere ich diese Ausgabe und kann ich GCC dazu bringen, dies für mich zu tun?

Martin Kristiansen
quelle

Antworten:

90

Ja, Sie können gcc verwenden, um Ihren ASM-Code zu kompilieren. Verwenden Sie -c für die Kompilierung wie folgt:

gcc -c file.S -o file.o

Dies gibt eine Objektcodedatei mit dem Namen file.o. Führen Sie die folgenden Schritte aus, um den Linker aufzurufen:

gcc file.o -o file
cyber_raj
quelle
30
Sie können auch nur verwendengcc file.S -o file
Breno Leitão
was ist mit "> als -o hallo.o hallo.s"? wie unter www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html angegeben . Die Reihenfolge des Prozesses scheint Vorverarbeitung ( .i-Datei), Kompilieren ( .s-Datei), Zusammenstellen ( .o-Datei) und Verknüpfen ( .exe-Datei) zu sein.
user1677716
@ user1677716: Ja, das gcc -cläuft, wenn Sie ihm eine .sDatei geben. Sie können verwenden gcc -v, um die ausgeführten Befehle anzuzeigen, z. B. gcc -v -c foo.soder gcc -v foo.sum sie zusammenzusetzen und zu verknüpfen . Der Verknüpfungsteil ist komplexer als nur ld foo.o; Es muss mit CRT-Startcode und Bibliotheken einschließlich libc ( -lc) verknüpft sein .
Peter Cordes
51

gccSie können eine Assembly-Datei als Eingabe verwenden und den Assembler nach Bedarf aufrufen. Es gibt jedoch eine Subtilität:

  • Wenn der Dateiname mit " .s" (Kleinbuchstaben) endet , wird gccder Assembler aufgerufen.
  • Wenn der Dateiname mit " .S" endet (Großbuchstaben 'S'), wird gccder C-Präprozessor auf die Quelldatei angewendet (dh er erkennt Anweisungen wie #ifund ersetzt Makros) und ruft dann den Assembler für das Ergebnis auf.

Im Allgemeinen möchten Sie also Folgendes tun:

gcc -S file.c -o file.s
gcc -c file.s
Thomas Pornin
quelle
Das sieht so aus, als würde es funktionieren, aber ich erhalte eine Fehlermeldung: 'Malformed Mach-o file'
Martin Kristiansen
Ich denke, Sie müssen das .SPräfix (Großbuchstaben) verwenden, sonst erkennt gcc einen anderen Dateityp ( .asmzum Beispiel fehlgeschlagen )
Jean-François Fabre
11

Sie können den Assemblycode in ein normales C-Programm einbetten. Hier ist eine gute Einführung . Mit der entsprechenden Syntax können Sie GCC auch mitteilen, dass Sie mit in C deklarierten Variablen interagieren möchten. Das folgende Programm weist gcc an, dass:

  • eax soll foo sein
  • ebx soll bar sein
  • Der Wert in eax wird nach Ausführung des Assembler-Codes in foo gespeichert

\ n

int main(void)
{
        int foo = 10, bar = 15;
        __asm__ __volatile__("addl  %%ebx,%%eax"
                             :"=a"(foo)
                             :"a"(foo), "b"(bar)
                             );
        printf("foo+bar=%d\n", foo);
        return 0;
}
Johannes Rudolph
quelle
4

Ja, gcc kann auch Assembly-Quellcode kompilieren. Alternativ können Sie asden Assembler aufrufen . (gcc ist nur ein "Treiber" -Programm, das Heuristiken verwendet, um C-Compiler, C ++ - Compiler, Assembler, Linker usw. aufzurufen.)

zvrba
quelle
1
Wie finde ich heraus, wie gcc verwendet hätte?
Martin Kristiansen
Außerdem habe ich Intel ICC herumliegen, welchen Assembler verwenden sie?
Martin Kristiansen
4
@ Martin, bitte darum gcc -v, seine Handlungen zu erzählen.
SK-Logik
2

Wenn Sie die Datei main.s haben. Sie können Objektdateien von GCCund auch generierenas

# gcc -c main.s
# as main.s -o main.o

Wenn Sie diesen Link überprüfen, können Sie einige Binutils von GCC kennenlernen. http://www.thegeekstuff.com/2017/01/gnu-binutils-commands/

Srinivas Achary
quelle
Beachten Sie, dass Sie keine Verknüpfung zu einer ausführbaren Datei herstellen können ld(ohne eine Reihe von Optionen hinzuzufügen): Sie möchten weiterhin gcc main.o -o maineine Verknüpfung mit dem CRT-Startcode und-lc
Peter Cordes
-1
nasm -f bin -o 2_hello 2_hello.asm
Hassan Maher
quelle
2
Dies ist eine ziemlich kurze Antwort. Könnten Sie bitte eine Erklärung hinzufügen? Vielleicht können Sie uns sagen, was die Parameter tun und was Sie anders machen als die anderen Antworten.
GameDroids
GCC generiert keine NASM-Syntax, sondern GAS mit AT & T oder .intel_syntax noprefix. Es gibt keine Kombination von GCC- und NASM-Optionen, mit denen Sie C zu asm mit GCC kompilieren und dann mit NASM zusammenstellen können.
Peter Cordes