# 实验步骤

# 安装 RISC-V 的交叉编译器

sudo apt-get install gcc-riscv64-linux-gnu

# 编写一个测试程序

image-20230312205719027

# 生成 RISC-V 的汇编代码

riscv64-linux-gnu-gcc -S -o risc_test.s risc_test.c

# 分析汇编代码

.file	"risc_test.c" 	; 原C代码文件名
	.option nopic
	.text
	.align	1				
	.globl	g				; g为全局符号
	.type	g, @function	; g定义为函数
g:
	add	sp,sp,-32			; sp = sp - 32, sp为栈顶指针
	sd	s0,24(sp)			; s0的值保存在sp+24的地址中, s0为栈底指针
	add	s0,sp,32			; s0 = sp + 32
	mv	a5,a0				; a5 = a0 
	sw	a5,-20(s0)			; a5的值保存在s0-20的地址中
	lw	a5,-20(s0)			; 将s0-20地址中的值保存在a5
	addw	a5,a5,3			; a5 = a5 + 3
	sext.w	a5,a5
	mv	a0,a5				; g函数的返回a5保存在a0中用于返回
	ld	s0,24(sp)			; s0 = sp + 24,恢复栈底指针原值
	add	sp,sp,32			; 恢复栈顶指针原值
	jr	ra					; 跳转,函数返回
	.size	g, .-g
	.align	1
	.globl	f				; f为全局符号
	.type	f, @function	; f定义为函数
f:
	add	sp,sp,-32			; sp = sp - 32, sp为栈顶指针
	sd	ra,24(sp)			; ra的值(返回地址)保存在sp+24的地址中
	sd	s0,16(sp)			; s0的值保存在sp+16的地址中, s0为栈底指针
	add	s0,sp,32			; s0 = sp + 32
	mv	a5,a0				; a5 = a0,保存函数传入进来的的参数
	sw	a5,-20(s0)a			; a5的值存放到s0-20指向的地址中
	lw	a5,-20(s0)			; 将s0-20地址中的值存放到a5中
	mv	a0,a5				; a0 = a5保存调用g函数的待传的参数
	call	g				; 调用g函数
	mv	a5,a0				; a5 = a0
	mv	a0,a5				; a0 = a5, f函数的返回值保存在a0中
	ld	ra,24(sp)			; ra = sp + 24, 得到返回地址
	ld	s0,16(sp)			; s0 = sp + 16, 将sp+16的值重新存储到s0栈底指针中,指向main函数的栈空间
	add	sp,sp,32			; sp = sp + 32, 指向main函数栈空间栈顶
	jr	ra					; 函数返回,回到mian函数
	.size	f, .-f
	.align	1
	.globl	main
	.type	main, @function
main:
	add	sp,sp,-16			; sp = sp - 16
	sd	ra,8(sp)			; ra存放的返回地址值放到sp+8
	sd	s0,0(sp)			; s0为栈底指针,将s0的值存放到sp指向的地址中
	add	s0,sp,16			; s0=sp+16,构造main函数的栈空间
	li	a0,8				; 保存函数调用的待传参数
	call	f				; 调用f函数
	mv	a5,a0				; a5 = a0, f函数返回值保存到a5中
	addw	a5,a5,1			; a5 = a5 + 1
	sext.w	a5,a5
	mv	a0,a5				; a0 = a5, 保存main函数的返回值
	ld	ra,8(sp)			; 得到返回地址
	ld	s0,0(sp)			; 恢复栈底指针
	add	sp,sp,16			; 恢复栈顶指针
	jr	ra					; 函数返回
	.size	main, .-main
	.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"