【RISC-V操作系统】从零开始写一个操作系统(五)RISCV汇编语言编程

本文介绍了RISC-V架构的汇编语言入门知识,包括汇编规则、指令类型和编码格式。讲解了标签、操作、注释的结构,以及RISC-V的32个通用寄存器。文章还提到了GNU工具链中的汇编程序编写,如宏定义,并概述了不同类型的指令,如R型、I型、S型、B型、U型和J型指令,以及它们的用途和格式。
摘要由CSDN通过智能技术生成

一、RISCV汇编入门

参考资料:

非特权手册

汇编器在线文档

缺点:

难读,难写,难移植。

优点:

灵活 ,强大。

特点:

适合参与直接操作硬件的场景。

需要对性能极致优化的地方。

1.risc汇编规则(gnu版本)

不同的汇编器可能规则不同。我们使用GNU工具链。

一个汇编程序(.s/.S)由多条语句组成(statement)。

一条语句由三部分组成:

[label:]  [operation] [comment]

标签,操作,注释。

# First RISC-V Assemble Sample

.macro do_nothing	# directive
	nop		# pseudo-instruction
	nop		# pseudo-instruction
.endm			# directive

	.text		# directive
	.global _start	# directive
_start: 		# Label
	li x6, 5	# pseudo-instruction
	li x7, 4	# pseudo-instruction
	add x5, x6, x7	# instruction
	do_nothing	# Calling macro
stop:	j stop		# statement in one line

	.end		# End of file

 

 label就是类似于一种变量,或者说地址,这也是中文意思:标签。

operation是操作指令,可以分为几类:

instruction指令
pseudo instruction伪指令
directive指示
macro(宏)

有的指令对应机器码(机器指令),例如 add x1,x2, x4

伪指令就是不对应原生的机器指令,是为了提高写代码效率,类似与多条指令组合,会被分解成真正的指令再翻译成机器语言。

directive的作用是通过.开头的的类似指令的形式,来控制代码生成的一些特殊处理。事实上是给汇编器看的东西不属于riscV标准。比如.end就是告诉汇编器到这结束了,后面的就不会再看了。.text就是告诉汇编器把代码存到text这个section内。在编译和链接章节内有提到。.global 类似与设置全局变量。start又是一个地址,把这个地址变为全局变量。不对应具体指令:只能在汇编器手册里看到。

的定义就是类似c语言的宏定义,比如代码内的do nothing。先定义后调用的形式大家应该能发现。变成两条nop,又被翻译。

注释:#,//,;,都可以,常用的是#。

2.汇编指令总览:操作对象

寄存器

32个通用寄存器,注意这里指的是我们文章仅涉及RV32I的寄存器组。每个寄存器都有别名。大家要仔细研究手册。

 手册机翻的中文版我也给大家放在开头了。

在riscv中hart的操作数据必须来自寄存器。

内存

HART可以执行在寄存器和内存之间的数据读写操作。

读写操作使用字节作为基本单位进行寻址。

RV32最多访问2^32个内存地址。

 3.汇编指令总览:指令编码格式

第一节也讲了类似的概念。

那么这里来讲真实的。

指令长度:ILEN1=32bit(RV32I)

指令对齐:IALIGN=32bit(RV32I)事实上指的是在内存里面,地址一定是4个字节的倍数,这就是对齐。当引入16bit指令时,对对齐的检查放宽到2字节(16bit)。

32个bit划分成不同的域。

不同的划分域的方式就是不同类型的指令。

手册内:

 

 opcode并不能直接决定指令类型,而是结合funct3(3bit)和funct7(7bit)部分才能确定。

riscv isa把rs1与rs2(两个源)以及rd(目的)放在相同的位置以方便解码。

  • 用于寄存器-寄存器操作的 R 类型指令,
  • 用于短立即数和访存 load 操作的 I 型指令,
  • 用于访存 store 操作的 S 型指令,
  • 用于条件跳转操作的 B 类型指令,
  • 用于长立即数的 U 型指令,
  • 用于无条件跳转的 J 型指令

第二十四章有这么一张指令opcode对照表。 这是满足imafd的G指令集。如果不知道我现在在说什么,请务必回去看之前的isa介绍那一篇文章。图中我们可以看到我们的opcode map给出第0位和第1位永远是11。那么还剩下5位,从第二位到第六位。那么这个表格行标题是第二位到第四位,列标题是第五位到第六位。

下面则是更详细的总表。

比如add指令:0110011,

0110011:-11是操作码的缺省位

0110011:查表行01

0110011:查表列100

得到op类型。

另外指令在内存中为小端序排列(低位字节排在内存的低地址。)

不了解这个可以自行查阅百度等。概念不难不在这赘述。

4.指令类型

  • 用于寄存器-寄存器操作的 R 类型指令,
  • 用于短立即数和访存 load 操作的 I 型指令,
  • 用于访存 store 操作的 S 型指令,
  • 用于条件跳转操作的 B 类型指令,
  • 用于长立即数的 U 型指令,
  • 用于无条件跳转的 J 型指令

具体的格式与他们分类有关。

R:register每条指令中有三个 fields,用于指定 3 个 寄存器参数
I:immediate每条指令除了带有两个寄存器参数外,还带有一个立即数参数(宽度为 12 bits)。
S:store每条指令除了带有两个寄存器参数外,还带有一个立即数参数(宽度为 12 bits,但 fields 的组织方式不同于 I-type)
B:branch每条指令除了带有两个寄存器参数外,还带有一个立即数参数(宽度为 12 bits,但取值为 2 的倍数)。
U:upper每条指令含有一个寄存器参数再加上一个立即数参数(宽度为 20 bits,用于表示一个立即数的高 20 位)
J:jump

每条指令含有一个寄存器参数再加上一个立即数参数(宽度为 20 bits)

寄存器一般都是5bit,为什么?========因为一共32个寄存器。

汇编指令分类还有更具体的,比如算数运算有哪几个,内存读写有哪几个等等。这里也不多谈。

第二十五章则是给出汇编的常见伪指令。

 

那么简介就到这里。下一站是汇编指令的详解。和我一起做好准备。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值