Подтвердить что ты не робот

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

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

int main(void) {return 0;}

Его можно скомпилировать с помощью gcc -o test test.c.

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

Я могу сгенерировать код сборки с помощью gcc -S test.c.

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

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

4b9b3361

Ответ 1

Это разные этапы с использованием 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

Ответ 2

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

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

Ответ 3

// 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 // OR $: gcc -c main.c -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

Привет, мир!

Источники:

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

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

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

Ответ 4

После выполнения gcc -S -o test.s test.c введите gcc -o test test.s.

Ответ 5

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

Ответ 6

Как вы можете или не можете знать, четыре этапа компиляции состоят в предварительной обработке (-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