RiscV汇编介绍(1)-编译过程

落爺英雄遲暮 提交于 2019-11-26 14:09:19

       把高层的c/c++源文件转化为可执行文件的过程如下图所示(linux操作系统为例):

image


以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!
用下面命令先生成目标文件,然后用riscv的objdump,可以看到生成riscv汇编。

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!