分析C代码编译成RISC-V汇编后如何执行

分析C代码编译成RISC-V汇编后如何执行

环境搭建

  1. 环境Ubuntu 22.04LTS

  2. 新建文件夹RISCV并进入

  3. 使用git下载工具链git clone --recursive https://github.com/riscv/riscv-gnu-toolchain

  4. 安装依赖sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

  5. 配置编译选项./configure --prefix=/opt/riscv --enable-multilib

  6. 编译make -j4,根据自己设备的核心数设置多线程

  7. 修改/etc/profile/opt/riscv/bin添加到PATH,并使用source /etc/profile重新加载

  8. 在终端中输入riscv64并使用tab补全,若能出现补全则为配置完成。

  9. 安装GCCsudo apt install gcc-risc64-unknown-elf

编译

  1. 编写测试代码

  2. 编译成汇编代码riscv64-unknown-elf-gcc -S riscv-test.c -o riscv-test.s

    -S:生成汇编代码*.s文件

    -o:把输出文件输出到指定文件里

分析

  1. 打开汇编代码

    	.file	"riscv-test.c"
    	.option nopic		# 与位置有关代码段
    	.attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
    	.attribute unaligned_access, 0	#我猜是禁止非对齐访问
    	.attribute stack_align, 16	# 堆栈16字节对齐
    	.text				# 代码段
    	.align	1			# 按2^1字节对齐
    	.globl	g			# 声明g为全局符号
    	.type	g, @function # 将g定义为一个函数
    g:
    	addi	sp,sp,-32	# 修改栈指针sp=sp-32,push
    	sd	s0,24(sp)		# 把s0保存到sp+24,s0表示帧指针fp
    	addi	s0,sp,32	# 栈底保存到s0,s0=sp+32
    	mv	a5,a0			# 将a0存放的参数值存入a5
    	sw	a5,-20(s0)		# 将a5中的字保存到s0-20
    	lw	a5,-20(s0)		# 将s0-20的字存入a5
    	addiw	a5,a5,3		# a5=a5+3,按word加
    	sext.w	a5,a5		# 将a5标记为扩展字(Sign extend word)
    	mv	a0,a5			# 将a5的值返回a0
    	ld	s0,24(sp)		# 恢复s0
    	addi	sp,sp,32	# 恢复sp
    	jr	ra				# 跳转到ra地址返回
    	.size	g, .-g		# 为了源代码兼容性
    	.align	1			# 按2^1字节对齐
    	.globl	f			# 声明f为全局符号
    	.type	f, @function # 将f定义为一个函数
    f:
    	addi	sp,sp,-32	# 修改栈指针sp=sp-32,push
    	sd	ra,24(sp)		# 将ra值保存到sp+24
    	sd	s0,16(sp)		# 将s0值保存到sp+16
    	addi	s0,sp,32	# 栈底保存到s0,s0=sp+32
    	mv	a5,a0			# 将a0存放的参数值存入a5
    	sw	a5,-20(s0)		# 将a5中的字保存到s0-20
    	lw	a5,-20(s0)		# 将s0-20的字存入a5
    	mv	a0,a5			# 将a5的值返回a0
    	call	g			# 调用函数g
    	mv	a5,a0			# 将返回来的值a0移入a5中
    	mv	a0,a5			# 将a5中的值移入返回值a0中
    	ld	ra,24(sp)		# 恢复ra
    	ld	s0,16(sp)		# 恢复s0
    	addi	sp,sp,32	# 恢复sp
    	jr	ra				# 跳转到ra地址返回
    	.size	f, .-f		# 为了源代码兼容性
    	.align	1			# 按2^1字节对齐
    	.globl	main		# 声明main为全局符号
    	.type	main, @function	 # 将main定义为一个函数
    main:
    	addi	sp,sp,-16	# 修改栈指针sp=sp-16,push
    	sd	ra,8(sp)		# 将ra值保存到sp+8
    	sd	s0,0(sp)		# 将s0值保存到sp+0
    	addi	s0,sp,16	# 栈底保存到s0,s0=sp+16
    	li	a0,8			# 立即数赋值a0=8
    	call	f			# 调用函数f
    	mv	a5,a0			# 将返回来的值a0移入a5中
    	addiw	a5,a5,1		# a5=a5+1,按word加
    	sext.w	a5,a5		# 将a5标记为扩展字(Sign extend word)
    	mv	a0,a5			# 将a5的值返回a0
    	ld	ra,8(sp)		# 恢复ra
    	ld	s0,0(sp)		# 恢复s0
    	addi	sp,sp,16	# 恢复sp
    	jr	ra				# 跳转到ra地址返回
    	.size	main, .-main # 为了源代码兼容性
    	.ident	"GCC: () 10.2.0"	# 为了源代码兼容性(accepted for source compatibility)
    

406

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值