Update chapter1.md

pull/1/head
Zhiyuan Shao 4 years ago
parent 611f74cb87
commit 9768a36c71

@ -57,7 +57,7 @@ RISC-V读做“risk-five”是一种典型的精简Reduced Instruction
图1.1列出了RV64IRV64G的整数指令子集的常用基础指令。
![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 0800rs2寄存器中的低位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
```

Loading…
Cancel
Save