当前位置:   article > 正文

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

riscv汇编语言教程

一、RISCV汇编入门

参考资料:

非特权手册

汇编器在线文档

  1. 缺点:
  2. 难读,难写,难移植。
  3. 优点:
  4. 灵活 ,强大。
  5. 特点:
  6. 适合参与直接操作硬件的场景。
  7. 需要对性能极致优化的地方。

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

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

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

一条语句由三部分组成:

[label:]  [operation] [comment]

标签,操作,注释。

  1. # First RISC-V Assemble Sample
  2. .macro do_nothing # directive
  3. nop # pseudo-instruction
  4. nop # pseudo-instruction
  5. .endm # directive
  6. .text # directive
  7. .global _start # directive
  8. _start: # Label
  9. li x6, 5 # pseudo-instruction
  10. li x7, 4 # pseudo-instruction
  11. add x5, x6, x7 # instruction
  12. do_nothing # Calling macro
  13. stop: j stop # statement in one line
  14. .end # End of file

 

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

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

  1. instruction指令
  2. pseudo instruction伪指令
  3. directive指示
  4. 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个寄存器。

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

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

 

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/461040
推荐阅读
相关标签
  

闽ICP备14008679号