RISC-V汇编
2022/6/8 1:22:39
本文主要是介绍RISC-V汇编,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
ASM@RISC-V
CPU寄存器
Register | ABI | Discription | Attribution |
---|---|---|---|
x0 | zero | 硬件常数0 | N/A |
x1 | ra | 返回地址 | Caller |
x2 | sp | 栈指针 | Callee |
x3 | gp | 全局指针 | - |
x4 | tp | 线程指针 | - |
x5-x7 | t0-t2 | 临时变量 | Caller |
x8 | s0/fp | 保存寄存器/帧指针 | Callee |
x9 | s1 | 保存寄存器 | Callee |
x10-x11 | a0-a1 | 函数参数/返回值 | Caller |
x12-x17 | a2-a7 | 函数参数 | Caller |
x18-x27 | s2-s11 | 保存寄存器 | Callee |
x28-x31 | t3-t6 | 临时变量 | Caller |
f0-f7 | ft0-ft7 | 浮点临时变量 | Caller |
f8-f9 | fs0-fs1 | 浮点保存寄存器 | Callee |
f10-f11 | fa0-fa1 | 浮点函数参数/返回值 | Caller |
f12-f17 | fa2-fa7 | 浮点函数参数 | Caller |
f18-f27 | fs2-fs11 | 浮点保存寄存器 | Callee |
f28-f31 | ft8-ft11 | 浮点临时变量 | Caller |
32位RISC-V(RV32)指令集概述
典型汇编语句
label: | opcode | operands | comment |
---|---|---|---|
标签 | 操作码 | 操作数 | 注释 |
- 标签:表示当前指令的位置标记
- 操作码:
- RISC-V标准指令
- 伪指令
- 用户自定义宏
- 操作数:
- 操作码所需的操作,与操作码之间以空格分开
- 符号、常量、或是符号与常量组成的表达式
指令格式
-
I型指令
imm[11:0] rs1 funct3 rd opcode [31:20] [19:15] [14:12] [11:7] [6:0] -
U型指令
imm[31:12] rd opcode [31:12] [11:7] [6:0] -
S型指令
imm[11:5] rs2 rs1 imm[4:0] rd opcode [31:25] [24:20] [19:15] [14:12] [11:7] [6:0] -
R型指令
funct7 rs2 rs1 funct3 rd opcode [31:25] [24:20] [19:15] [14:12] [11:7] [6:0] -
B型指令
-
J型指令
RV32I基本指令集
算术指令
-
add
- addi(add immediate)
-
or
- ori(OR Immediate)
-
xor(eXclusive OR)
- xori(eXclusive OR Immediate)
-
s- sll(Shift Left Logical)
- slli(Shift Left Logical Immediate)
- sra(Shift Right Arithmetic)
- srai(Shift Right Arithmetic Immediate)
- srl(Shift Right Logical)
- srli(Shift Right Logical Immediate)
- sll(Shift Left Logical)
-
sub(SUBtract)
-
lui(Load Upper Immediate)
将一个16位的立即数填入寄存器的高16位中,低16位则补零 -
auipc(Add Upper Immediate to PC)
-
slt(Set Less Than)
- slti(Set Less Than Immediate)
- sltiu(Set Less Than Immediate Unsigned)
- slti(Set Less Than Immediate)
加载指令
-
load- lb(Load Byte)
- lbu(Load Byte Unsigned)
- lh(Load Halfword)
读16位,符号位拓展后写入寄存器rd中- lhu(Load Halfword Unsigned)
读16位,高位补0,写入寄存器rd中
- lhu(Load Halfword Unsigned)
- lw(Load Word)
从存储器中读回一个32位的数据,写入寄存器rd中
- lb(Load Byte)
-
store- sb(store Byte)
- sh(store Halfword)
- sw(store Word)
条件分支指令
branch- beq(branch equal)
- bne(branch not equal)
- bge(Branch Greater than or Equal)
- bgeu(Branch Greater than or Equal Unsigned)
- blt(Branch Less Than)
- bltu(Branch Less Than Unsigned)
跳转控制指令
- jal(Jump And Link)
- jalr(Jump And Link Register)
寄存器屏障指令
-
fence
-
break
- ebreak
-
call
- ecall
-
csr- csrrc(Control Status Register Read & Clear bit)
- csrrci(Control Status Register Read & Clear bit Immediate)
- csrrs(Control Status Register Read & Set bit)
- csrrsi(Control Status Register Read & Set bit Immediate)
- csrrw(Control Status Register Read & Write bit)
- csrrwi(Control Status Register Read & Write bit Immediate)
- csrrc(Control Status Register Read & Clear bit)
RV32标准拓展指令
RV32M标准拓展指令
- mul
- mulh
- mulhsu
- mulhu
- mulh
- div
- divu
- rem
- remu
RV32A标准拓展指令
- lr.w
- sc.w
amo- amoswap.w
- amoadd.w
- amoxor.w
- amoand.w
- amoor.w
- amomin.w
- amomax.w
- amominu.w
- amomaxu.w
RV32F标准拓展指令
- flw
- fsw
- fmadd.s
- fmsub.s
- fnmsub.s
- snmadd.s
- fadd.s
- fsub.s
- fmul.s
- fdiv.s
- fsqrt.s
- fsgnj.s
- fsgnjn.s
- fsgnjx.s
- fmin.s
- fmax.s
- fcvt.w.s
- fcvt.wu.s
- fmv.x.s
- feq.s
- flt.s
- fclass.s
- fcvt.s.w
- fcvt.s.wu
- fmv.s.x
伪指令
实际上是由基本指令组合而成
加载伪指令
- la(Load Address)
加载地址 - ld(LoaD)
加载全局参数
算术伪指令
- nop
- li(Load Immediate)
加载立即数 - mv(MOV)
- not
- neg
- negw
- sext
- seqz
- snez
- sltz
- sgtz
浮点算术伪指令
- fmv.s
- fabs.s
- fneg.s
- fmv.d
- fabs.d
- feng.d
条件分支伪指令
- beqz
- bnez
- blez
- bgez
- bltz
- bgtz
跳转控制伪指令
- j
- jal
- jr
- jalr
- ret
- tail
启动
-
.global(.globl)
伪操作,用于定义全局符号,使链接过程中能被其他程序文件可见,类似于extern -
.local
伪操作,用于定义局部符号,仅当前程序文件可见 -
.file
伪操作,用于指示汇编器该汇编程序的逻辑文件名opcode oprands .file "filename" -
.section
- .text
- .data
- .rodata
- .bss
-
.type
-
.align
- .balign
-
.zero
-
.byte
- 2byte
- 4byte
- 8byte
-
.float
- .double
-
.word
- .half
- .dword
-
.string
-
.equ
-
.weak
伪操作,同时创建符号并定义为弱属性。如果该符号已定义,则设置此符号为弱属性- 在汇编程序中,符号的默认属性为强(strong)
如果符号的属性为弱,则可无需定义具体内容,常用于预留空符号并通过汇编语法检查。当另外存在一个属性为强的同名符号实体时会自动覆盖并链接
-
.pushsection - .popsection
-
.marco - .endm
宏 -
.comm(.common)
-
.option
注释
以符号 # 或 ; 作为分隔号,当行分隔号以后的部分会被视作注释
代指
- rd(Register Destination)
指目标寄存器,实际代码中可以是t0、t1等
代码格式(C语言嵌套汇编)
在C语言文件中嵌入汇编代码,除对固定地址寄存器并直接进行操作外,需要将变量等参数传入汇编程序中,才能保证操作有效,想要传入参数,需要通过操作符列表来完成
关键字
-
asm
为GCC的关键字,表示进行内联汇编操作,也可以使用前后各带两个下划线的__asm__
,_asm_
是GCC关键字asm的宏定义。 -
volatile
或者_volatile_
、_volatile_
或volatile
,均为宏定义。如果添加了该关键字,则通知编译器避免对后续括号内添加汇编程序进行任何优化,以保持其原状 -
汇编指令列表
即需要嵌入的汇编指令,每条指令必须被双引号括起来(作为字符串),两条指令之前必须以“\n”或者“;”作为分隔符。如果没有添加分隔符,相连的字符串将会被合并成为一个字符串。内部语法与汇编程序一样
标记符号
-
%
后面跟标签则为指定,若为数字则是从操作符列表顺序选择 -
-
“ ”
引号中的限制字符串,用于约束此操作数变量的属性,常用的约束如:-
r
代表使用编译器自动分配的寄存器来存储该操作数变量 -
m
字母“m”代表使用内存地址来存储该操作数变量,如果同时指明“rm”则编译器自动选择最优方案 -
=
对于输出操作数而言,等号代表输出变量用作输出,原来的值会被新值替换,此约束不适用于输入操作数 -
+
代表输出变量不仅作为输出,还作为输入,此约束不适用于输入操作数
-
-
( )
圆括号中填入C/C++变量或者表达式
输出操作符之间需使用逗号分割
操作符列表
-
输出资源表
: [ ]"=r"( ), [ ]"=r"( ), ···
-
输入资源表
: [ ]"r"( ), [ ]"r"( ), ···
-
影响资源表
: " ", "", ···
用于告知编译器当前内联汇编语句可能会对某些寄存器或内存进行修改,使得编译器在优化时将其因素考虑进去
- 隐式表
除了使用%[字符]
中明确的符号命名指定之外,还可以使用%数字
的方式进行隐含指定。从0开始,依次表示操作符列表中所有的输出操作数与输入操作数。
范例
int abc = 10,cba = 20; printf("%d & %d\n",abc,cba); asm volatile( "mv %[da],%3\n" "add %2,%1,%0\n" "li %3,12\n" : [da]"=r"(abc), "=r"(cba) // Working : "r"(abc), [db]"r"(cba) // Working : "t1", "t2"//, "x7" ); printf("%d & %d\n",abc,cba);
输出结果为:
10 20 (修改前) 40 12 (修改后)
这篇关于RISC-V汇编的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享