RSIC-V汇编语言基础

Zard-1996 2022-05-16 23:06:29

RISC-V(发音为“risk-five”)是一个基于精简指令集(RISC)原则的开源指令集架构(ISA)。

RISC-V 被设计成可以支持丰富的定制化和特殊化。基本整数 ISA 可被一个或者多个可选 指令集扩展进行增强,但是基本整数指令集不能被重新定义。最基础的指令是RV32I,即32位的指令。这个是所有的RISC-V处理器都需要实现的指令。RISC-V体系结构可以在这个基础指令集上进行扩展:RV64I,这是64位的基础指令扩展;RV32M是乘法指令扩展;RV32F是单精度浮点扩展;RV32D是双精度浮点扩展等。RV32IMFD就代表了把对应的模块扩展到基础的RV32I中。本文只讨论RV32I。

一、RSIC-V CPU的寄存器

RV32I 基础指令集总共定义了 32 个 32 位的通用寄存器。它们分别被标记为x0 ~ x31。其中零号寄存器 x0 是只读寄存器,其值永远为零。在用汇编语言编写时,这 32 个寄存器的名称也根据其在调用约定中的职能而被重新命名。具体如下表

寄存器名称汇编名称功能描述调用返回后其值是否会保证不变

x0

zero零寄存器未定义
x1ra返回地址
x2sp栈指针
x3gp全局指针未定义
x4tp线程指针未定义
x5t0临时寄存器
x6t1临时寄存器
x7t2临时寄存器
x8s0/fp该寄存器需要被调函数予以保存,或也可用作调用栈的帧指针
x9s1该寄存器需要被调函数予以保存
x10~x11a0~a1函数参数或返回值
x12~x17a2~a7函数参数
x18~x27s2~s11该寄存器需要被调函数予以保存
x28~x31t3~t6临时寄存器

除32个通用寄存器外,RSIC-V还定义一个PC寄存器,该寄存器指向当前正在执行的指令的内存地址。

二、常用的 RSIC-V 汇编指令

 RISC-V汇编指令分类主要有以下几种:算术运算指令、逻辑运算指令、位移运算指令、内存读写指令、分支与跳转指令。如下图所示,汇编语言的操作与指令是一一对应的,汇编程序可以很简单快速的翻译成机器指令。

在基本ISA中,有四种核心指令格式(R/I/S/U),如下图所示。所有的指令都是固定 32位长度的,并且在存储器中必须在4字节边界对齐。当发生一个条件分支或者无条件转移 而且目标地址不是对齐到4字节时,将会产生一个指令地址不对齐的异常。如果条件分支没 有发生(not taken),那么将不会产生一个取指不对齐异常。

 下面我们对常用指令进行介绍。

算术运算

  • dd rd,rs1,rs2
    :将寄存器rs1与rs2的值相加并写入寄存器rd。
  • sub rd,rs1,rs2
    :将寄存器rs1与rs2的值相减并写入寄存器rd。
  • addi rd,rs1,imm
    :将寄存器rs1的值与立即数imm相加并存入寄存器rd。
  • mul rd,rs1,rs2
    :将寄存器rs1与rs2的值相乘并写入寄存器rd。
  • div rd,rs1,rs2
    :将寄存器rs1除以寄存器rs2的值,向零舍入并写入寄存器rd。
  • rem rd,rs1,rs2
    :将寄存器rs1模寄存器rs2的值并写入寄存器rd。

以上运算发生溢出时会自动截断高位,将低32位写入寄存器中。

逻辑运算

  • and rd,rs1,rs2
    :将寄存器rs1与rs2的值按位与并写入寄存器rd。
  • andi rd,rs1,imm
    :将寄存器rs1的值与立即数imm的值按位与并写入寄存器rd。
  • or rd,rs1,rs2
    :将寄存器rs1与rs2的值按位或并写入寄存器rd。
  • ori rd,rs1,imm
    :将寄存器rs1的值与立即数imm的值按位或并写入寄存器rd。
  • xor rd,rs1,rs2
    :将寄存器rs1与rs2的值按位异或并写入寄存器rd。
  • xori rd,rs1,imm
    :将寄存器rs1的值与立即数imm的值按位异或并写入寄存器rd。

移位运算

  • sll rd,rs1,rs2
    :将寄存器rs1的值左移寄存器rs2的值这么多位,并写入寄存器rd。
  • slli rd,rs1,imm
    :将寄存器rs1的值左移立即数imm的值这么多位,并写入寄存器rd。
  • srl rd,rs1,rs2
    :将寄存器rs1的值逻辑右移寄存器rs2的值这么多位,并写入寄存器rd。
  • srli rd,rs1,imm
    :将寄存器rs1的值逻辑右移立即数imm的值这么多位,并写入寄存器rd。
  • sra rd,rs1,rs2
    :将寄存器rs1的值算数右移寄存器rs2的值这么多位,并写入寄存器rd。
  • srai rd,rs1,imm
    :将寄存器rs1的值算数右移立即数imm的值这么多位,并写入寄存器rd。

左移会在右边补0,逻辑右移会在最高位添0,算数右移在最高位添加符号位。

区分算数右移和逻辑右移,是从计算的角度考虑的:左移一位等于乘2,右移一位等于除2是算数的规律;无论正数负数,在右边补0都等于乘2;而负数进行逻辑右移的结果不等于除以2,需要用算数右移;而若只有算术右移,则无符号数的运算又会受影响。

数据传输指令

现代计算机以字节(byte,1byte=8bits)为基本单位,而内存本身可被视作由byte组成的一维数组,地址从0开始。(word)则是存取数据的另一个单位,在RISC-V中1word=4Bytes=32bits,在其他体系结构中可能会发生变化。

  • lb rd,offset(rs1)
    :从地址为寄存器rs1的值加offset的主存中读一个字节,符号扩展后存入rd
  • lh rd,offset(rs1)
    :从地址为寄存器rs1的值加offset的主存中读半个字,符号扩展后存入rd
  • lw rd,offset(rs1)
    :从地址为寄存器rs1的值加offset的主存中读一个字,符号扩展后存入rd
  • lbu rd,offset(rs1)
    :从地址为寄存器rs1的值加offset的主存中读一个无符号的字节,零扩展后存入rd
  • lhu rd,offset(rs1)
    :从地址为寄存器rs1的值加offset的主存中读半个无符号的字,零扩展后存入rd
  • lwu rd,offset(rs1)
    :从地址为寄存器rs1的值加offset的主存中读一个无符号的字,零扩展后存入rd
  • sb rs1,offset(rs2)
    :把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的8位
  • sh rs1,offset(rs2)
    :把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的16位
  • sw rs1,offset(rs2)
    :把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的32位

比较指令

有符号数:

  • slt rd,rs1,rs2
    :若rs1的值小于rs1的值,rd置为1,否则置为0
  • slti rd,rs1,imm
    :若rs1的值小于立即数imm,rd置为1,否则置为0

无符号数:

  • sltu rd,rs1,rs2
    :若rs1的值小于rs1的值,rd置为1,否则置为0
  • sltiu rd,rs1,imm
    :若rs1的值小于立即数imm,rd置为1,否则置为0

条件分支指令

  • beq rs1,rs2,lable
    :若rs1的值等于rs2的值,程序跳转到lable处继续执行
  • bne rs1,rs2,lable
    :若rs1的值不等于rs2的值,程序跳转到lable处继续执行
  • blt rs1,rs2,lable
    :若rs1的值小于rs2的值,程序跳转到lable处继续执行
  • bge rs1,rs2,lable
    :若rs1的值大于等于rs2的值,程序跳转到lable处继续执行

blt和bge也有无符号版本bltu和bgeu。

无条件跳转指令

  • j label
    :程序直接跳转到lable处继续执行
  • jal rd,label
    :用于调用函数,把下一条指令的地址保存在rd中(通常用x1),然后跳转到label处继续执行
  • jalr rd,offset(rs)
    :可用于函数返回,把下一条指令的地址存到rd中,然后跳转到rs+offset地址处的指令继续执行。若rd=x0就是单纯的跳转(x0不能被修改)

 三、分析完整的 RSIC-V 汇编程序

我们对下面的程序的汇编代码进行分析。

int g(int x)
{
	return x + 3;
}
int f(int x)
{
	return g(x);
}
int main(){
  return f(8) + 1;
}

其汇编代码为 

	.file	"hello.c"
	.option nopic
	.text
	.align	1
	.globl	g
	.type	g, @function
main:
	addi	sp,sp,-16            //栈指针-16,构造栈空间
	sd	ra,8(sp)                 //把ra放到mem(sp + 8)中
	sd	s0,0(sp)                 //把s0放到mem(sp)中
                                 //以上两步保存寄存器的值
	addi	s0,sp,16             //把sp+16放到s0中,s0保存的是栈底指针
	li	a0,8                     //a0 = 8
	call	f                    //调用f
	mv	a5,a0                    //a5 = a0,a0保存的是调用函数的返回值
	addiw	a5,a5,1              //a5 = a5 + 1
	sext.w	a5,a5
	mv	a0,a5                    //a0 = a5,a0保存返回值
	ld	ra,8(sp)                 //ra = mem(sp + 8)
	ld	s0,0(sp)                 //s0 = mem(sp)
                                 //以上两步恢复寄存器的值
	addi	sp,sp,16             //sp = sp + 16,释放栈空间
	jr	ra
	.size	main, .-main
	.ident	"GCC: (GNU) 10.2.0"
f:
	addi	sp,sp,-32            //栈指针-32,构造栈空间
	sd	ra,24(sp)                //把ra放到mem(sp + 24)中
	sd	s0,16(sp)                //把s0放到mem(sp + 16)中
	addi	s0,sp,32             //把sp+16放到s0中,s0保存的是栈底指针
	mv	a5,a0                    //a0 = a5
	sw	a5,-20(s0)               //mem(s0 - 20) = a5
	lw	a5,-20(s0)               //a5 = mem(s0 - 20)
	mv	a0,a5                    //a5 = a0
	call	g                    //调用g
	mv	a5,a0                    //a5 = a0
	mv	a0,a5                    //a0 = a5
                                 //以上几行除了调用g之外在做无用功,猜测可能程序太简单了😂
	ld	ra,24(sp)                //ra = mem(sp + 24)
	ld	s0,16(sp)                //s0 = mem(sp + 16),返回现场
	addi	sp,sp,32             //sp = sp + 32,退栈
	jr	ra
	.size	f, .-f
	.align	1
	.globl	main
	.type	main, @function
g:
	addi	sp,sp,-32            //栈指针-32,构造栈空间
	sd	s0,24(sp)                //把s0放到mem(sp + 24)中
                                 //因为函数g没有调用函数,可能因此就没有保存栈指针
	addi	s0,sp,32             //新的栈底
	mv	a5,a0                    //又是一串无用功
	sw	a5,-20(s0)
	lw	a5,-20(s0)
	addiw	a5,a5,3              //参数从a0最后传到a5,a5 = a5 + 3
	sext.w	a5,a5
	mv	a0,a5                    //返回结果放到a0
	ld	s0,24(sp)                
	addi	sp,sp,32             //恢复现场
	jr	ra
	.size	g, .-g
	.align	1
	.globl	f
	.type	f, @function

函数的堆栈框架

由上面的程序和汇编代码,我们可以猜测出RSIC-V的函数调用栈的框架。

call指令是一条伪指令,由auipc和jlar两条指令组成,作用就是调用子过程。

 参考

https://zhuanlan.zhihu.com/p/496767749

https://blog.csdn.net/Cerman/article/details/122020984

https://whycan.com/files/members/7090/riscv-spec-v2.1%E4%B8%AD%E6%96%87%E7%89%88.pdf

https://blog.csdn.net/qq_41976613/article/details/90550181

331

...全文
229 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
riscv-asm:risc-v汇编语言
Tcl中的risc-v汇编程序这个简单的risc-v汇编程序支持带有几个标准扩展的rv32和rv64。它的输出是一个原始列表,列出了源代码行,地址和字节(以十六进制表示)。当前不支持编写ELF。指令集和扩展名: rv32G(IMAFD_...
RISC-V汇编语言(5)
汇编语言RISC-V 汇编语言入门汇编语言概念简介汇编语言语法介绍RISC-V 汇编指令总览RISC-V 汇编指令操作对象RISC-V 汇编指令编码格式指令格式(format)主机字节序 (HBO - Host Byte Order)RISC-V 汇编指令分类RISC-...
RISC-V汇编简介
RISC-V汇编简介 汇编语言有3类指令组成: a.汇编指令:机器码的助记符,有对应的机器码,可以翻译成对应的二进制机器码。 b.伪指令:没有对应的机器码,由汇编器解释执行,可以翻译成多条汇编指令,也可以没有对应...
risc-v汇编语言输出斐波那契数列前6位数(仅供参考,不一定正确)
.data array_A: .word 3,5,7,9,11 .text la x8,array_A #x8为数组A首地址,x9=&A[i] add x9,x8,x0 #x9=&A[0] add x10,x0,x0 #nextTerm=0 add x11,x0,x0 #i=0 addi x13,x0,6 #循环次数 ...l
RISC-V汇编指令
了解汇编之前,我们需要先了解为什么需要汇编?以下是我的理解:机器执行的命令都是些二进制的机器码,我们需要对机器进行编程需要记住这些机器码,这是对于程序员很不友好的,所以前人就用一些汇编指令取替代这些...
代码中的软件工程

566

社区成员

817

社区内容

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

加载中

查看更多榜单
社区公告

《代码中的软件工程》

《代码中的软件工程》配套资料

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

+ 用AI写文章

聚圣源鸡眼挖出来的肉刺图监督权玉蒲团之偷情黎小田给公司起名称的软件平凡的世界在线阅读联名 起诉陈二狗的妖孽人生txt天龙八部地图逆转检察官起名英文名字世界名将对白起的评价国家药品不良反应监测系统女孩起名大全属土929电影女生姓方起名大全移动积分兑换话费姓何的起名字大全适合能起名字的诗词养父演员表公司起名风水ikea.com婚姻保卫战演员表仁者无敌演员表用夏起名的女孩名字大全僵尸企业祝寿蛋糕起名浏览器兼容性起名女孩姓许焕字起名淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

聚圣源 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化