Выполнение шагов gcc вручную, компиляция, сборка, компоновка - PullRequest
28 голосов
/ 16 декабря 2011

Если у вас простая программа на C, например,

int main(void) {return 0;}

Может быть скомпилировано с gcc -o test test.c.

Как я понимаю, gcc выполняет компиляцию, сборку, а затем компоновку. Последние два шага выполняются при запуске as и ld.

Я могу сгенерировать ассемблерный код, используя gcc -S test.c.

Что бы вы напечатали в терминале, чтобы преобразовать ассемблерный код в исполняемый файл?

(причина для этого - изучение ассемблера)

Ответы [ 6 ]

57 голосов
/ 16 декабря 2011

Это разные этапы, использующие gcc

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
3 голосов
/ 16 декабря 2011

gcc test.s -o test скомпилирует test из test.s для вас.

NASM также может стоить вашего времени - это может быть проще / удобнее, чем gcc для компиляции сборки.

1 голос
/ 19 мая 2019
// main.c
#include <stdio.h>

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

Для предварительной обработки, компиляции, сборки и, наконец, связывания простой вышеупомянутой программы hello world выполните следующие действия:

Шаг 1/4) Предварительная обработка main.c для генерации main.i:

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

Шаг 2/4) Скомпилируйте main.i для генерации main.s:

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

Шаг 3/4) Соберите main.s для генерации main.o:

$: as main.s -o main.o

ПРИМЕЧАНИЕ. Вы можете объединить вышеупомянутые шаги 1, 2 и 3, используя флаг -c (small C) для gcc:

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

Шаг 4/4) Свяжите main.o с другими необходимыми объектными файлами, а именно, crti.o & crtn.o (они определяют прологи и эпилоги функций соответственно), crt1.o (содержит символ _start для начальной загрузки начального выполнения программа), путь libc.so или флаг -lc для libc, а затем, наконец, задайте имя динамического компоновщика, чтобы сгенерировать динамически связанный исполняемый файл ELF:

На 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

ИЛИ (если вы хотите указать путь к libc.so)

$: 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

На 32-битном 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

ИЛИ (если вы хотите указать путь к libc.so)

$: 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.so.3 -o main_ELF_executable

Затем вы можете запустить исполняемый файл ELF 'main_ELF_executable':

$: ./main_ELF_executable

Hello World!

Источники:

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

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

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

1 голос
/ 16 декабря 2011

После того, как вы введете gcc -S -o test.s test.c, введите gcc -o test test.s.

0 голосов
/ 06 апреля 2016

Как вы можете знать или не знать, четыре стадии компиляции - это предварительная обработка (-E), компиляция в сборку (-S), сборка в объектный код (-c) и, наконец, компоновка. Самым сложным для меня было выяснить, как использовать выход препроцессора. Вот как это сделать:

gcc -E hello.c | gcc -S -xc -o hello.s -
gcc -c hello.s -o hello.o
gcc hello.o -o hello
0 голосов
/ 16 декабря 2011

Вы можете gcc запускать и останавливать процесс компиляции в любом месте.gcc test.s -o test будет компилировать test.s из сборки в исполняемый файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...