Die Schritte von gcc manuell ausführen, kompilieren, assemblieren, verknüpfen

Lesezeit: 8 Minuten

Wenn Sie ein einfaches C-Programm haben, z

int main(void) {return 0;}

Es kann mit kompiliert werden gcc -o test test.c.

Soweit ich weiß, führt gcc das Kompilieren, Assemblieren und dann Verknüpfen durch. Die beiden letztgenannten Schritte werden dadurch erreicht, dass es läuft as und ld.

Ich kann den Assembler-Code generieren, indem ich verwende gcc -S test.c.

Was würden Sie in ein Terminal eingeben, um den Assemblercode in eine ausführbare Datei umzuwandeln?

(Der Grund dafür ist, Montage zu lernen)

  • Tatsächlich führt es zuerst die Vorverarbeitung durch, dann das Kompilieren, dann das Assemblieren und dann das Linken. Die Vorverarbeitung ist möglicherweise ein nicht trivialer Teil des Prozesses, insbesondere wenn Sie Boost verwenden …

    – Kerrek SB

    15. Dezember 2011 um 22:57 Uhr

  • Du kannst den … benutzen -v Parameter, um zu sehen, wie GCC seine Unterprogramme aufruft, z gcc -o test test.c -v

    – macht

    15. Dezember 2011 um 23:22 Uhr

  • Überprüfen Sie dies, indem Sie “-###” an gcc übergeben

    – Johannes Schaub – litb

    14. August 2021 um 18:54 Uhr

Benutzeravatar von quicoju
quicoju

Dies sind die verschiedenen Phasen, in denen gcc verwendet wird

gcc -E  --> Preprocessor, but don't compile
gcc -S  --> Compile but don't assemble
gcc -c  --> Preprocess, compile, and assemble, but don't link
gcc with no switch will link your object files and generate the executable

  • Aktuelle Versionen von GCC haben keinen separaten Präprozessor mehr (Sie können jedoch nur eine Vorverarbeitung wie oben anfordern)

    – Vonbrand

    20. Januar 2013 um 21:14 Uhr

  • Gute Antwort, schade, dass es nicht zu viel erklärt

    – CristiFati

    3. März 2018 um 1:45 Uhr

  • Wenn jemand wie ich endlich als separaten Befehl verlinken möchte, zeigt nur die Antwort von ZeZNiQ, wie es geht.

    – Marischa

    29. September 2019 um 14:35 Uhr

Benutzeravatar von ZeZNiQ
ZeZNiQ

// main.c
#include <stdio.h>

int main(void)
{
        printf("Hello World !\n");
        return 0;
}

Zum Vorverarbeiten, Kompilieren, Assemblieren und schließlich zum endgültigen Verknüpfen des einfachen oben genannten Hallo-Welt-Programms befolgen Sie die folgenden Schritte:

Schritt 1/4) main.c vorverarbeiten, um main.i zu generieren:

$: gcc -E main.c -o main.i

HINWEIS: Sie können den C-Präprozessor auch direkt aufrufen:

$: cpp main.c -o main.i

Schritt 2/4) main.i kompilieren, um main.s zu generieren:

$: gcc -S main.i -o main.s

Schritt 3/4) main.s zusammenbauen, um main.o zu generieren:

$: as main.s -o main.o

HINWEIS: Sie können die oben genannten Schritte 1, 2 und 3 kombinieren, indem Sie das Flag -c (kleines C) von gcc verwenden:

$: gcc -c main.s -o main.o // OR $: gcc -c main.c -o main.o

Schritt 4/4) Verknüpfen Sie main.o mit anderen notwendigen Objektdateien, nämlich crti.o & crtn.o (sie definieren Funktionsprologs bzw. -eplogs), crt1.o (enthält _start-Symbol zum Bootstrapping der anfänglichen Ausführung des Programms) , libc.so-Pfad oder -lc-Flag für libc und legen Sie dann schließlich den Namen des dynamischen Linkers fest, um eine dynamisch verknüpfte ausführbare ELF-Datei zu generieren:

Auf x86_64:

$: ld /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o /usr/lib/x86_64-linux-gnu/crt1.o -lc main.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main_ELF_executable

ODER (wenn Sie den Pfad zu libc.so angeben möchten)

$: ld /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/libc.so main.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main_ELF_executable

Auf 32-Bit-ARM:

$: ld /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/arm-linux-gnueabihf/crt1.o -lc main.o -dynamic-linker /lib/ld-linux.so.3 -o main_ELF_executable

ODER (wenn Sie den Pfad zu libc.so angeben möchten)

$: ld /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/arm-linux-gnueabihf/crt1.o /usr/lib/arm-linux-gnueabihf/libc.so main.o -dynamic-linker /lib/ld-linux-armhf.so.3 -o main_ELF_executable

Sie können dann die ausführbare ELF-Datei ‚main_ELF_executable‘ ausführen:

$: ./main_ELF_executable

Hallo Welt !

Quellen:

https://linux.die.net/man/1/gcc

https://linux.die.net/man/1/ld

https://dev.gentoo.org/~vapier/crt.txt

  • Wollte upvoten, aber Sie sollten auf keinen Fall eine solche Befehlszeile zum Verlinken verwenden – lassen Sie GCC stattdessen den richtigen Linker-Befehl aufrufen!

    – Antti Haapala – Слава Україні

    19. Mai 2019 um 18:21 Uhr

  • Das stimmt, aber das OP fragte: „Was würden Sie in ein Terminal eingeben, um den Assemblercode in eine ausführbare Datei umzuwandeln?“, also wollte ich nur zeigen, wie man jeden Schritt manuell ausführt. Aus diesem Grund habe ich auch die Quellen gepostet, um OP zu ermutigen, mehr zu lernen, einschließlich, aber nicht beschränkt auf die Tatsache, dass die Verknüpfungsreihenfolge ebenfalls wichtig ist.

    – ZeZNiQ

    20. Mai 2019 um 1:16 Uhr

  • Wenn jemand wie ich endlich als separaten Befehl verlinken möchte, zeigt nur die Antwort von ZeZNiQ, wie es geht.

    – Marischa

    29. September 2019 um 14:37 Uhr

gcc test.s -o test werde die kompilieren test aus test.s für dich.

NASM könnte auch Ihre Zeit wert sein – es könnte einfacher / freundlicher sein als gcc zum Kompilieren von Assemblies.

  • Nicht wirklich. gcc erledigt eine Menge systemabhängiger Bürokratie für Sie, in voller Kompatibilität mit der Art und Weise, wie es andere Teile Ihres Projekts handhabt.

    – Vonbrand

    20. Januar 2013 um 21:16 Uhr

Nachdem du es getan hast gcc -S -o test.s test.cTyp gcc -o test test.s.

Wie Sie vielleicht wissen oder nicht wissen, bestehen die vier Phasen der Kompilierung darin, vorzuverarbeiten (-E), zu Assembler zu kompilieren (-S), zu Objektcode zu assemblieren (-c) und schließlich zu verknüpfen. Das Schwierigste für mich war herauszufinden, wie man die Ausgabe des Präprozessors verwendet. So geht’s:

gcc -E hello.c | gcc -S -xc -o hello.s -
gcc -c hello.s -o hello.o
gcc hello.o -o hello

Kevins Benutzeravatar
Kevin

Du kannst haben gcc Starten und stoppen Sie den Kompilierungsprozess, wo immer Sie wollen. gcc test.s -o test werde es kompilieren lassen test.s von der Assemblierung in eine ausführbare Datei.

Benutzeravatar von Sakura Adachi
Sakura Adachi

Was ich tat, war zuerst, dass ich den Präprozessor durchführte
clang++ test.cpp -E > test.i
dann kompiliert es mit …
clang++ -S test.i
Es sollte eine Assembly-Datei test.s erstellen … und dann die Maschinen-Insturction-Datei erstellen
as test.s -o test.o
Jetzt müssen Sie es verlinken, was für dumme Leute wie mich etwas verwirrend ist … also kennen wir die Argumente für unseren letzten Prozess nicht, der das Verlinken ist … um es herauszufinden … auszuführen
clang++ -v test.s
es sollte Ihnen einen großen Text von irgendetwas geben … finden Sie diese Zeile “-dynamic-linker” … es gibt definitiv einen -dynamic-linker in Ihrem Ausgabetext … kopieren Sie jetzt den Text von -dynamic-linker in den Rest von die Ausgabe … kopiere einfach alles danach einschließlich “-dynamic-linker” … jetzt habe ich …

-dynamic-linker /system/bin/linker -o a.out /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../.. /../lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0 -L/data/data/com.termux/files/ usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib -L/data/data/com.termux/files/usr/lib/gcc/arm- linux-androideabi/11.1.0/../../.. -L/data/data/com.termux/files/usr/lib -L/system/lib /data/data/com.termux/files/usr /tmp/test-169b42.o -lc++_shared -lgcc -ldl -lm -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1. 0/../../../../lib/crtend_android.o

In diesem Fall müssen Sie ändern, wo sich Ihre Objektdatei befindet … in meinem Fall ist es /data/data/com.termux/files/usr/tmp/test-169b42.o … ich muss es ändern wo meine test.o-Datei ist … /data/data/com.termux/files/home/CPP/Cpp_Log/hello_world/test.o … hier ist meine test.o-Datei … also das Argument wir müssen passieren ist …

-dynamic-linker /system/bin/linker -o a.out /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../.. /../lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0 -L/data/data/com.termux/files/ usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib -L/data/data/com.termux/files/usr/lib/gcc/arm- linux-androideabi/11.1.0/../../.. -L/data/data/com.termux/files/usr/lib -L/system/lib /data/data/com.termux/files/home /CPP/Cpp_Log/hello_world/main.o -lc++_shared -lgcc -ldl -lm -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/ 11.1.0/../../../../lib/crtend_android.o

jetzt zum verlinken…benutze die ld … so lautet der Befehl ld args -o test oder in unserem Fall …

ld -dynamic-linker /system/bin/linker -o a.out /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0 -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib -L/data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../.. -L/data/data/com.termux/files/usr/lib -L/system/lib /data/data/com.termux/files/home/CPP/Cpp_Log/hello_world/main.o -lc++_shared -lgcc -ldl -lm -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/gcc/arm-linux-androideabi/11.1.0/../../../../lib/crtend_android.o -pie -o test

da andriod 5+ nur pie elf ausführbare Dateien ausführen kann … habe ich auch das “-pie” (positionsunabhängige ausführbare Datei) vor dem -o-Test hinzugefügt …

Jetzt sollte es Ihnen eine ausführbare Testdatei geben … führen Sie sie einfach durch ./test

es sollte funktionieren

1409090cookie-checkDie Schritte von gcc manuell ausführen, kompilieren, assemblieren, verknüpfen

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

Privacy policy