C代码编译为RISC-V汇编代码后的执行过程

无名 2022-05-17 14:34:39

一、 RISC-V通用寄存器
RISC-V架构支持32位或者64位的架构,32 位架构由RV32表示,其每个通用寄存器的宽度为32比特; 64位架构由RV64表示,其每个通用寄存器的宽度为64比特。

 

RISC-V架构的整数通用寄存器组,包含32个(I 架构)或者16个(E架构)通用整数寄存器,其中整数寄存器0被预留为常数0,其他的31个(I架构)或者15个(E架构)为普通的通用整数寄存器。

如果使用浮点模块(F或者D),则需要另外一个独立的浮点寄存器组,包含32个通用浮点寄存器。如果仅使用F模块的浮点指令子集,则每个通用浮点寄存器的宽度为32比特;如果使用了D模块的浮点指令子集,则每个通用浮点寄存器的宽度为64比特。

在流水线中能够尽快地读取通用寄存器组,往往是处理器流水线设计的期望之一,这样可以提高处理器性能和优化时序。这个看似简单的道理在很多现存的商用RISC架构中都难以实现,因为经过多年反复修改不断添加新指令后,其指令编码中的寄存器索引位置变得非常凌乱,给译码器造成了负担。

得益于后发优势和总结了多年来处理器发展的经验,RISC-V的指令集编码非常规整,指令所需的通用寄存器的索引都被放在固定的位置,如下所示。因此指令译码器可以非常便捷地译码出寄存器索引,然后读取通用寄存器组。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ29kZV9jb3B5MQ==,size_20,color_FFFFFF,t_70,g_se,x_16

 

二、c代码从编译到执行

从c代码源文件,到能够执行文件,须要如下几个步骤:c++

  • 预处理/编译
  • 汇编
  • 链接
  • image

 接下来以编译test.c为例,展示C代码编译为RISC-V汇编代码的执行过程

1、编写test.c

#include<stdio.h>

int factor(int n){
	int result = 1;
	while(n){
		result *= n;
		n--;
	}
	return result;
}
int main(){
	int x = 0;
	scanf("%d",&x);
	int result = factor(x);
	printf("%d",result);
	return 0;
}

2.使用gcc –E test.c –o test.i, 将源文件test.c文件预处理生成test.i

3. 编译, gcc –S testi –o test.s, 生成汇编程序test.s,对于x86系统,生成x86汇编代码。

	.file	"test.c"
	.text
	.globl	factor
	.type	factor, @function
factor:
.LFB0:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	%edi, -20(%rbp)
	movl	$1, -4(%rbp)
	jmp	.L2
.L3:
	movl	-4(%rbp), %eax
	imull	-20(%rbp), %eax
	movl	%eax, -4(%rbp)
	subl	$1, -20(%rbp)
.L2:
	cmpl	$0, -20(%rbp)
	jne	.L3
	movl	-4(%rbp), %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	factor, .-factor
	.section	.rodata
.LC0:
	.string	"%d"
	.text
	.globl	main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movq	%fs:40, %rax
	movq	%rax, -8(%rbp)
	xorl	%eax, %eax
	movl	$0, -16(%rbp)
	leaq	-16(%rbp), %rax
	movq	%rax, %rsi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	__isoc99_scanf@PLT
	movl	-16(%rbp), %eax
	movl	%eax, %edi
	call	factor
	movl	%eax, -12(%rbp)
	movl	-12(%rbp), %eax
	movl	%eax, %esi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	movq	-8(%rbp), %rdx
	subq	%fs:40, %rdx
	je	.L7
	call	__stack_chk_fail@PLT
.L7:
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 10.3.0-1ubuntu1) 10.3.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	 1f - 0f
	.long	 4f - 1f
	.long	 5
0:
	.string	 "GNU"
1:
	.align 8
	.long	 0xc0000002
	.long	 3f - 2f
2:
	.long	 0x3
3:
	.align 8
4:

4.汇编 gcc –c test.s –o test.o, 生成目标机器码。3d

5.连接,和系统库文件进行连接,ld test.o –o test, 执行会出错,只靠一个test.o不能生成一个完整的可执行文件。code

gcc test.c –o test 能够直接生成可执行文件。

学号:287

...全文
268 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧