type
status
date
slug
summary
tags
category
icon
password
RISC-V指令集简略学习笔记
本文主要记录的是对riscv的学习笔记(什么废话)
ISA
Instruction Set Architecture,指令集架构,是硬件电路向上层软件程序提供的接口规范。其中包括了数据类型、寄存器、指令、寻址方法、中断处理等等。著名的ISA有x86、ARM、SPARC、MIPS、RISC-V等等。
IBM 360是第一台定义了指令集架构的机器(石头门也干了)
好处就是上层开发不用关心硬件的内部逻辑。
CISC与RISC
Complex Instruction Set Computing:复杂指令集,指令数目多,程序长度短。x86就是一种复杂指令集
Reduced Instruction Set Computing:精简指令集,指令个数少,程序长度长。
RISC-V可以通俗理解为精简指令集的一个版本,最早是用于教学目的。(经典大学出神人)
ISA的宽度
指的是CPU中通用寄存器的宽度,决定了寻址范围的大小。
值得注意的是,ISA的宽度与指令编码长度无关。
RISC-V ISA的命名规范
RV+数字(字宽,bit为单位)+字母(指令集模块集合)
如:RV32IMA、RV64GC等(特定组合IMAFD⇒G,通用指令集)
通用寄存器
pc(程序指针寄存器)在risc-v的是非暴露的,并不能通过指令集访问。
HART
Hardware Thread,硬件线程,
HART的概念类似于“处理器上的虚拟机”,与具体的指令执行流一一对应,而和真实处理器核数无关。一般不讨论真实处理器个数,只讨论HART个数。
特权级别(Privileged level)
由上到下用户权限逐渐升高,不同的级别下有不同的一套寄存器,低级别不能够跨级别访问高级寄存器
内存管理与保护
M级别下下访问的都是实际地址,不支持虚拟地址访问。
异常&中断
异常:遇到异常之后会执行异常处理程序,执行完会回到原来出错的指令
中断:遇到中断之后会执行中断处理程序,执行完之后会跳转到原指令的下一个指令
RISC-V 汇编语言编程
一个完整的的RISC-V汇编程序由多条语句(statement)组成。每条语句由[label:][operation][comment]三个部分组成(支持缺项,三个都缺就是空行)。
[label:]:任何以冒号结尾的都会被认为是标号,相当于是给地址起了个名字
[comment]:注释,以#开始的内容都会在程序执行时被忽略
[operation]:
instruction:指令,直接对应二进制字符串。
pseudo-instruction:伪指令,汇编器会将其翻译成多条实际指令。(提高编写效率)
directive:指示,以’.’开头,控制汇编器产生代码的方式等,不与实际指令相对应。不属于risc-v指令集的一部分,只与汇编器有关
macro:采用.macro/.endm自定义的宏(两个语句夹着的就是一个宏定义)
指令操作对象
寄存器:通用寄存器(RV32I对应的寄存器)共有32个,以x0~x31编号,其中x0不可写,读取时值恒为零,其他寄存器均可读可写,在RV架构上,Hart在执行算术运算和逻辑运算时,所操作的数据必须直接来自于寄存器。
内存:Hart可以执行寄存器和内存之间的数据读写操作,读写操作使用字节(Byte)为单位进行寻址。
指令编码格式
不同类型的type对应不同的field划分。
不同的指令格式(format):R-Register、I-Immediate、S-Store、B-Branch、U-Upper、J-Jump
funct3/7的含义是对应的function占用3/7个bit位
查表:inst[1:0]代表这个域的第一和第零位始终唯一,在此基础上,结合横纵的数据确定具体的opcode,如10 011 11代表NMADD指令,在RISC-V手册中就有所有指令对应的编码格式与指令对照表。
小端序排列,较小的地址位于右侧
指令编写与应用
先放一个网上扒的程序在这里……
栈&堆
和学C语言时候的堆栈没啥区别,不如说实际上堆、栈的定义和使用啥语言本来就无关(什么爸爸像儿子)
栈区的管理是由程序自动进行的,函数结束就会把栈帧回收,栈区不算太大,如果递归调用太多或者函数内声明太多变量啥的就会爆栈(stackoverflow)在栈区的变量叫自动变量,不需要人为维护
堆区是程序运行时用于动态分配内存的区域。它在程序的生命周期内可以动态地分配和释放内存,适用于需要在运行时确定大小的数据结构。堆区在 RISC-V 编程中与其他架构中的作用相同,主要用于管理动态内存分配。
内存布局
典型的程序内存布局如下:
堆区位于栈区和 BSS 段之间,随着内存的动态分配和释放,堆区的大小可以动态变化。初始化过的全局变量啥的位于读写数据段(.data段)
示例代码
以下是一个简单的示例,展示了如何在 RISC-V 编程中使用堆区进行动态内存分配:
在这个示例中,
malloc
函数用于在堆区动态分配一个整数数组,free
函数用于释放已分配的内存。函数调用约定
函数调用时,所使用到的调用参数、返回地址、返回的参数或数据信息由谁声明、存储或管理,需要有Caller和Callee的约定。
- 有关寄存器的编程约定
- 有关函数跳转和返回指令的编程约定
- 有关被调用函数实现方式的编程约定
)
- Author:XiaoYi
- URL:https://notion-next-ashen-seven.vercel.app/article/10d555f7-8779-8042-bdde-f4654bd6e305
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!