|
|
|
@ -57,7 +57,7 @@ RISC-V(读做“risk-five”)是一种典型的精简(Reduced Instruction
|
|
|
|
|
|
|
|
|
|
图1.1列出了RV64I(RV64G的整数指令子集)的常用基础指令。
|
|
|
|
|
|
|
|
|
|
![fig1_1](pictures/fig1_1.png)
|
|
|
|
|
<img src="pictures/fig1_1.png" alt="fig1_1" style="zoom:80%;" />
|
|
|
|
|
|
|
|
|
|
图1.1 RV64I的常用基础指令,带下划线的粗体字母从左到右连起来构成RV64I指令。
|
|
|
|
|
|
|
|
|
@ -93,13 +93,12 @@ RISC-V汇编指令的格式与8086汇编是截然不同的。以最基础的加
|
|
|
|
|
|
|
|
|
|
以上的例子中,假设A=0x0000 0000 0000 0800,rs2寄存器中的低位4字节数值为0x1234ABCD,则sw指令执行完后内存中的数值为:
|
|
|
|
|
|
|
|
|
|
`[0x0000 0000 0000 0800] = 0xCD`
|
|
|
|
|
|
|
|
|
|
`[0x0000 0000 0000 0801] = 0xAB`
|
|
|
|
|
|
|
|
|
|
`[0x0000 0000 0000 0802] = 0x34`
|
|
|
|
|
|
|
|
|
|
`[0x0000 0000 0000 0803] = 0x12`
|
|
|
|
|
```
|
|
|
|
|
[0x0000 0000 0000 0800] = 0xCD
|
|
|
|
|
[0x0000 0000 0000 0801] = 0xAB
|
|
|
|
|
[0x0000 0000 0000 0802] = 0x34
|
|
|
|
|
[0x0000 0000 0000 0803] = 0x12
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -115,15 +114,17 @@ RISC-V汇编指令的格式与8086汇编是截然不同的。以最基础的加
|
|
|
|
|
|
|
|
|
|
该语句中“asm”也可以由“__asm__”来代替。在“asm”后面有时也会加上“__volatile__”表示编译器不要对括弧内的汇编代码进行任何优化,保持指令的原样。“asm”后面括号里面的便是汇编指令。例如:
|
|
|
|
|
|
|
|
|
|
`asm(“li x17,81”); //将立即数81存入x17寄存器`
|
|
|
|
|
|
|
|
|
|
`asm(“ecall”); //调用ecall指令(作用类似8086上的int指令)`
|
|
|
|
|
```
|
|
|
|
|
asm(“li x17,81”); //将立即数81存入x17寄存器
|
|
|
|
|
asm(“ecall”); //调用ecall指令(作用类似8086上的int指令)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
编译器碰到以上语句后,会将引号中的汇编语句直接翻译成对应的机器码,放到所生成的目标代码中。这两行代码的作用是调用81号软中断(即1.4节中的trap),但因为它们是相邻的汇编语句,所以可以用以下的形式书写:
|
|
|
|
|
|
|
|
|
|
`asm(“li x17,81\n\t”`
|
|
|
|
|
|
|
|
|
|
`“ecall”);`
|
|
|
|
|
```
|
|
|
|
|
asm(“li x17,81\n\t”
|
|
|
|
|
“ecall”);`
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
也就是采用分隔符“\n\t”隔开多条汇编指令。对于编译器而言,以上两种写法是等效的。实际上GCC编译器在处理内联汇编语句时,是要把asm(…)的内容“打印”到汇编文件中,所以格式控制字符是必要的。
|
|
|
|
|
|
|
|
|
@ -131,17 +132,14 @@ RISC-V汇编指令的格式与8086汇编是截然不同的。以最基础的加
|
|
|
|
|
|
|
|
|
|
扩展内联汇编使得嵌入在C语言中的代码能够带输入、输出参数,同时将被汇编代码块改变的寄存器“通知”给GCC编译器,作为后者在调度寄存器时的参考。扩展内联汇编的格式为:
|
|
|
|
|
|
|
|
|
|
`asm volatile(`
|
|
|
|
|
|
|
|
|
|
`"statements"(汇编语句模板):`
|
|
|
|
|
|
|
|
|
|
`output_regs(输出部分):`
|
|
|
|
|
|
|
|
|
|
`input_regs(输入部分):`
|
|
|
|
|
|
|
|
|
|
`clobbered_regs(破坏描述部分)`
|
|
|
|
|
|
|
|
|
|
`) ;`
|
|
|
|
|
```
|
|
|
|
|
asm volatile(
|
|
|
|
|
"statements"(汇编语句模板):
|
|
|
|
|
output_regs(输出部分):
|
|
|
|
|
input_regs(输入部分):
|
|
|
|
|
clobbered_regs(破坏描述部分)
|
|
|
|
|
) ;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
其中asm 表示后面的代码为内嵌汇编,也可以写作__asm__;volatile 表示不想让编译器对里面的汇编代码进行优化,也可以写作__volatile__ 。"statements"是汇编语句模板;output_regs是内联汇编的输出部分,可以理解为将要被汇编语句修改的寄存器组;input_regs是内联汇编的输入部分,即语句执行所需要的输入寄存器;clobbered_regs是破坏描述部分,代表将要被汇编语句改变(破坏)的内容。扩展内联汇编中汇编语句模版是必须要的,其它3部分则都是可选内容,以下对这些部分分别进行解释:
|
|
|
|
|
|
|
|
|
@ -191,57 +189,32 @@ RISC-V汇编指令的格式与8086汇编是截然不同的。以最基础的加
|
|
|
|
|
我们再看一个稍微大一点的例子,通过这个例子我们希望能尽量把以上的知识点串起来,加深读者对RISC-V汇编语言的理解。假设有以下C语言程序test_asm.c,其源代码如例1.1所示:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
`1 #include <stdio.h>`
|
|
|
|
|
|
|
|
|
|
`2`
|
|
|
|
|
|
|
|
|
|
`3 void bar()`
|
|
|
|
|
|
|
|
|
|
`4 {`
|
|
|
|
|
|
|
|
|
|
`5 asm volatile( "li s5, 300" );`
|
|
|
|
|
|
|
|
|
|
`6 }`
|
|
|
|
|
|
|
|
|
|
`7`
|
|
|
|
|
|
|
|
|
|
`8 int foo( int foo_arg )`
|
|
|
|
|
|
|
|
|
|
`9 {`
|
|
|
|
|
|
|
|
|
|
`10 int x;`
|
|
|
|
|
|
|
|
|
|
`11 asm volatile( "li s5, 500" );`
|
|
|
|
|
|
|
|
|
|
`12 bar();`
|
|
|
|
|
|
|
|
|
|
`13 asm volatile (`
|
|
|
|
|
|
|
|
|
|
`14 "sd s5,%0"`
|
|
|
|
|
|
|
|
|
|
`15 :"=m"(x)`
|
|
|
|
|
|
|
|
|
|
`16 :`
|
|
|
|
|
|
|
|
|
|
`17 : "memory");`
|
|
|
|
|
|
|
|
|
|
`18 printf( "x=%d\n", x );`
|
|
|
|
|
|
|
|
|
|
`19 return 10;`
|
|
|
|
|
|
|
|
|
|
`20 }`
|
|
|
|
|
|
|
|
|
|
`21`
|
|
|
|
|
|
|
|
|
|
`22 int main()`
|
|
|
|
|
|
|
|
|
|
`23 {`
|
|
|
|
|
|
|
|
|
|
`24 foo( 10 );`
|
|
|
|
|
|
|
|
|
|
`25 return 0;`
|
|
|
|
|
|
|
|
|
|
`26 }`
|
|
|
|
|
1 #include <stdio.h>
|
|
|
|
|
2
|
|
|
|
|
3 void bar()
|
|
|
|
|
4 {
|
|
|
|
|
5 asm volatile( "li s5, 300" );
|
|
|
|
|
6 }
|
|
|
|
|
7
|
|
|
|
|
8 int foo( int foo_arg )
|
|
|
|
|
9 {
|
|
|
|
|
10 int x;
|
|
|
|
|
11 asm volatile( "li s5, 500" );
|
|
|
|
|
12 bar();
|
|
|
|
|
13 asm volatile (
|
|
|
|
|
14 "sd s5,%0"
|
|
|
|
|
15 :"=m"(x)
|
|
|
|
|
16 :
|
|
|
|
|
17 : "memory");
|
|
|
|
|
18 printf( "x=%d\n", x );
|
|
|
|
|
19 return 10;
|
|
|
|
|
20 }
|
|
|
|
|
21
|
|
|
|
|
22 int main()
|
|
|
|
|
23 {
|
|
|
|
|
24 foo( 10 );
|
|
|
|
|
25 return 0;
|
|
|
|
|
26 }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
例1.1 test_asm.c代码列表
|
|
|
|
@ -266,89 +239,47 @@ RISC-V汇编指令的格式与8086汇编是截然不同的。以最基础的加
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
00000000000101a4 <bar>:
|
|
|
|
|
|
|
|
|
|
101a4: ff010113 addi sp,sp,-16
|
|
|
|
|
|
|
|
|
|
101a8: 00813423 sd s0,8(sp)
|
|
|
|
|
|
|
|
|
|
101ac: 01010413 addi s0,sp,16
|
|
|
|
|
|
|
|
|
|
101b0: 12c00a93 li s5,300
|
|
|
|
|
|
|
|
|
|
101b4: 00000013 nop
|
|
|
|
|
|
|
|
|
|
101b8: 00813403 ld s0,8(sp)
|
|
|
|
|
|
|
|
|
|
101bc: 01010113 addi sp,sp,16
|
|
|
|
|
|
|
|
|
|
101c0: 00008067 ret
|
|
|
|
|
|
|
|
|
|
00000000000101c4 <foo>:
|
|
|
|
|
|
|
|
|
|
101c4: fd010113 addi sp,sp,-48
|
|
|
|
|
|
|
|
|
|
101c8: 02113423 sd ra,40(sp)
|
|
|
|
|
|
|
|
|
|
101cc: 02813023 sd s0,32(sp)
|
|
|
|
|
|
|
|
|
|
101d0: 03010413 addi s0,sp,48
|
|
|
|
|
|
|
|
|
|
101d4: 00050793 mv a5,a0
|
|
|
|
|
|
|
|
|
|
101d8: fcf42e23 sw a5,-36(s0)
|
|
|
|
|
|
|
|
|
|
101dc: 1f400a93 li s5,500
|
|
|
|
|
|
|
|
|
|
101e0: fc5ff0ef jal ra,101a4 <bar>
|
|
|
|
|
|
|
|
|
|
101e4: ff543623 sd s5,-20(s0)
|
|
|
|
|
|
|
|
|
|
101e8: fec42783 lw a5,-20(s0)
|
|
|
|
|
|
|
|
|
|
101ec: 00078593 mv a1,a5
|
|
|
|
|
|
|
|
|
|
101f0: 0001c7b7 lui a5,0x1c
|
|
|
|
|
|
|
|
|
|
101f4: f7078513 addi a0,a5,-144 # 1bf70 <__clzdi2+0x2e>
|
|
|
|
|
|
|
|
|
|
101f8: 1e2000ef jal ra,103da <printf>
|
|
|
|
|
|
|
|
|
|
101fc: 00a00793 li a5,10
|
|
|
|
|
|
|
|
|
|
10200: 00078513 mv a0,a5
|
|
|
|
|
|
|
|
|
|
10204: 02813083 ld ra,40(sp)
|
|
|
|
|
|
|
|
|
|
10208: 02013403 ld s0,32(sp)
|
|
|
|
|
|
|
|
|
|
1020c: 03010113 addi sp,sp,48
|
|
|
|
|
|
|
|
|
|
10210: 00008067 ret
|
|
|
|
|
|
|
|
|
|
0000000000010214 <main>:
|
|
|
|
|
|
|
|
|
|
10214: ff010113 addi sp,sp,-16
|
|
|
|
|
|
|
|
|
|
10218: 00113423 sd ra,8(sp)
|
|
|
|
|
|
|
|
|
|
1021c: 00813023 sd s0,0(sp)
|
|
|
|
|
|
|
|
|
|
10220: 01010413 addi s0,sp,16
|
|
|
|
|
|
|
|
|
|
10224: 00a00513 li a0,10
|
|
|
|
|
|
|
|
|
|
10228: f9dff0ef jal ra,101c4 <foo>
|
|
|
|
|
|
|
|
|
|
1022c: 00000793 li a5,0
|
|
|
|
|
|
|
|
|
|
10230: 00078513 mv a0,a5
|
|
|
|
|
|
|
|
|
|
10234: 00813083 ld ra,8(sp)
|
|
|
|
|
|
|
|
|
|
10238: 00013403 ld s0,0(sp)
|
|
|
|
|
|
|
|
|
|
1023c: 01010113 addi sp,sp,16
|
|
|
|
|
|
|
|
|
|
10240: 00008067 ret
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|