简体   繁体   English

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

[英]Running gcc's steps manually, compiling, assembling, linking

If you have a simple C program, like 如果你有一个简单的C程序,比如

int main(void) {return 0;}

It can be compiled with gcc -o test test.c . 它可以用gcc -o test test.c编译。

As I understand, gcc performs compiling, assembling then linking. 据我所知,gcc执行编译,组装然后链接。 The latter two steps are achieved by it running as and ld . 后两个步骤是通过运行asld来实现的。

I can generate the assembly code by using gcc -S test.c . 我可以使用gcc -S test.c生成汇编代码。

What would you type into a terminal, to convert the assembly code into an executable? 你会在终端中输入什么内容,将汇编代码转换为可执行文件?

(the reason for doing so is to learn assembly) (这样做的原因是学习装配)

These are the different stages using gcc 这些是使用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

gcc test.s -o test will compile the test from test.s for you. gcc test.s -o test将为您编译test.stest

NASM might also be worth your time -- it might be easier / more friendly than gcc for compiling assembly. NASM可能也值得你花时间 - 它可能比gcc编译汇编更容易/更友好。

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

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

For preprocessing, compiling, assembling and then finally linking the simple aforementioned hello world program, follow the steps below: 对于预处理,编译,组装,然后最终链接上述简单的hello world程序,请按照以下步骤操作:

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

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

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

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

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

$: as main.s -o main.o

NOTE: You can combine the aforementioned steps 1, 2 and 3 by using the -c (small C) flag of gcc: 注意:您可以使用gcc的-c(小C)标志组合上述步骤1,2和3:

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

Step 4/4) Link main.o with other necessary object files namely, crti.o & crtn.o (they define function prologs & epilogs, respectively), crt1.o (contains _start symbol for bootstrapping the initial execution of the program), libc.so path or -lc flag for libc and then finally set the name of the dynamic linker, to generate a dynamically linked ELF executable: 步骤4/4)将main.o链接到其他必要的目标文件,即crti.o和crtn.o(它们分别定义函数prolog和epilog),crt1.o(包含用于引导程序初始执行的_start符号) ,libc.so为libc的路径或-lc标志,然后最后设置动态链接器的名称,以生成动态链接的ELF可执行文件:

On x86_64: 在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

OR (if you'd like to specify path to libc.so) 或者(如果你想指定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

On 32-bit ARM: 在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

OR (if you'd like to specify path to libc.so) 或者(如果你想指定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

You can then run the ELF executable 'main_ELF_executable': 然后,您可以运行ELF可执行文件'main_ELF_executable':

$: ./main_ELF_executable

Hello World ! 你好,世界 !

Sources: 资料来源:

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

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

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

执行gcc -S -o test.s test.c ,键入gcc -o test test.s

As you may or may not know, the four stages of compilation are to preprocess (-E), compile to assembly (-S), assemble to object code (-c), and finally link. 您可能知道也可能不知道,编译的四个阶段是预处理(-E),编译到汇编(-S),汇编到目标代码(-c),最后链接。 The hardest for me to figure out was how to use the preprocessor output. 我最难弄明白的是如何使用预处理器输出。 Here's how to do it: 这是怎么做的:

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

You can have gcc start and stop the compilation process wherever you want. 您可以让gcc在任何地方启动和停止编译过程。 gcc test.s -o test will have it compile test.s from assembly into an executable. gcc test.s -o test将把test.s从汇编编译成可执行文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM