手动运行gcc的步骤,编译,组装,链接

che*_*ers 33 c gcc

如果你有一个简单的C程序,比如

int main(void) {return 0;}
Run Code Online (Sandbox Code Playgroud)

它可以编译 gcc -o test test.c.

据我所知,gcc执行编译,组装然后链接.后两步是通过运行as和实现的ld.

我可以使用生成汇编代码gcc -S test.c.

你会在终端中输入什么内容,将汇编代码转换为可执行文件?

(这样做的原因是学习装配)

qui*_*oju 61

这些是使用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
Run Code Online (Sandbox Code Playgroud)

  • 当前版本的GCC不再具有单独的预处理器(尽管如此,您可以要求仅进行预处理) (3认同)

ZeZ*_*NiQ 18

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

int main(void)
{
        printf("Hello World !\n");
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

对于上述简单的 hello world 程序的预处理、编译、组装和最终链接,请按照以下步骤操作:

步骤 1/4) 预处理 main.c 以生成 main.i:

$: gcc -E main.c -o main.i
Run Code Online (Sandbox Code Playgroud)

注意:您也可以直接调用 C 预处理器:

$: cpp main.c -o main.i
Run Code Online (Sandbox Code Playgroud)

步骤 2/4) 编译 main.i 以生成 main.s:

$: gcc -S main.i -o main.s
Run Code Online (Sandbox Code Playgroud)

步骤 3/4) 组装 main.s 以生成 main.o:

$: as main.s -o main.o
Run Code Online (Sandbox Code Playgroud)

注意:您可以使用 gcc 的 -c(小 C)标志组合上述步骤 1、2 和 3:

$: gcc -c main.s -o main.o // OR $: gcc -c main.c -o main.o
Run Code Online (Sandbox Code Playgroud)

步骤 4/4) 将 main.o 与其他必要的目标文件链接,即 crti.o 和 crtn.o(它们分别定义函数 prologs 和 epilogs)、crt1.o(包含用于引导程序初始执行的 _start 符号) , libc.so path or -lc flag for 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
Run Code Online (Sandbox Code Playgroud)

或(如果您想指定 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
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)

或(如果您想指定 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-armhf.so.3 -o main_ELF_executable
Run Code Online (Sandbox Code Playgroud)

然后,您可以运行 ELF 可执行文件“main_ELF_executable”:

$: ./main_ELF_executable
Run Code Online (Sandbox Code Playgroud)

你好,世界 !

资料来源:

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

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

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

  • 这是真的,但 OP 询问“你会在终端中输入什么,将汇编代码转换为可执行文件?”,所以我只想展示如何手动执行每个步骤。这就是为什么我还发布了来源以鼓励 OP 了解更多信息,包括但不限于链接顺序也很重要这一事实。 (5认同)
  • 如果像我这样的人最终想作为单独的命令链接,只有 ZeZNiQ 的回答显示了如何操作。 (2认同)