把高层的c/c++源文件转化为可执行文件的过程如下图所示(linux操作系统为例):
以hello.c程序为例,我们看下编译,汇编,链接到生产可执行文件的过程。
1.hello.c代码如下:
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
2.预处理hello.c,生产hello.i 文件,预处理主要展开宏定义,处理条件编译指令;处理#include 预编译指令,插入包含的文件;添加行号,文件标识符,以便编译时候产生调用的行号以及编译错误警告行号;保留所有的#pragma 编译器指令,后续编译过程需要使用它们。预处理可以看作是编译的一部分。
//gcc -E选项使得gcc在预编译完后就停止 gcc -E hello.c -o hello.i
3.编译过程,就是把c语言代码转化称相应汇编代码。比如x86系统中,就转化为x86的汇编。
//gcc -S选项使得gcc在编译完后停止,生成汇编代码 gcc -S hello.i -o hello.s
hello.s汇编代码为:
.file "hello.c"
.text
.section .rodata
.LC0:
.string "Hello World!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rdi
call puts@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits
~4.汇编,对生成的汇编程序hello.s进行处理,生成处理器识别的指令。执行下面的命令,生成目标文件hello.o。目标文件为elf格式的可重定向文件。
//gcc的-c选项在生成目标文件后停止 gcc -c hello.s -o hello.o
或者直接调用汇编器as
as -c hello.s -o hello.o
5.链接,把汇编以后的目标文件和系统的库文件链接,生成elf格式的可执行文件。默认情况下,gcc链接动态链接库so文件,如果使用参数 -static, 则使用静态库,使用静态库,可执行文件要大很多。
gcc hello.c -o hello .hello Hello World!
6.查看可执行文件大小和查看链接的动态链接库。
kaguo@ubuntu:~/riscv/riscv-tools/riscv-tools/riscv-gnu-toolchain$ size hello text data bss dec hex filename 1515 600 8 2123 84b hello kaguo@ubuntu:~/riscv/riscv-tools/riscv-tools/riscv-gnu-toolchain$ ldd hello linux-vdso.so.1 (0x00007ffc963f9000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f02ef548000) /lib64/ld-linux-x86-64.so.2 (0x00007f02efb3b000)
我们也可以用下面的命令,把源文件编译成riscv架构的可执行文件。用spike模拟器执行文件。
kaguo@ubuntu:~/riscv/riscv-tools/riscv-tools/riscv-gnu-toolchain$ riscv64-unknown-elf-gcc-8.3.0 -o hello hello.c
kaguo@ubuntu:~/riscv/riscv-tools/riscv-tools/riscv-gnu-toolchain$ spike pk hello
bbl loader
Hello World!
riscv64-unknown-elf-gcc-8.3.0 -o hello.o -c hello.c
kaguo@ubuntu:~/riscv/riscv-tools/riscv-tools/riscv-gnu-toolchain$ riscv64-unknown-elf-objdump -D hello.o
hello.o: file format elf64-littleriscv
Disassembly of section .text:
0000000000000000 <main>:
0: 1141 addi sp,sp,-16
2: e406 sd ra,8(sp)
4: e022 sd s0,0(sp)
6: 0800 addi s0,sp,16
8: 000007b7 lui a5,0x0
c: 00078513 mv a0,a5
10: 00000097 auipc ra,0x0
14: 000080e7 jalr ra # 10 <main+0x10>
18: 4781 li a5,0
1a: 853e mv a0,a5
1c: 60a2 ld ra,8(sp)
1e: 6402 ld s0,0(sp)
20: 0141 addi sp,sp,16
22: 8082 ret
Disassembly of section .rodata:
0000000000000000 <.LC0>:
0: 6548 ld a0,136(a0)
2: 6c6c ld a1,216(s0)
4: 6f57206f j 72ef8 <.LC0+0x72ef8>
8: 6c72 ld s8,280(sp)
a: 2164 fld fs1,192(a0)
...
Disassembly of section .comment:
0000000000000000 <.comment>:
0: 4700 lw s0,8(a4)
2: 203a4343 fmadd.s ft6,fs4,ft3,ft4,rmm
6: 4728 lw a0,72(a4)
8: 554e lw a0,240(sp)
a: 2029 0x2029
c: 2e38 fld fa4,88(a2)
e: 00302e33 sgtz t3,gp
