- RISC-V體系結(jié)構(gòu)編程與實(shí)踐(第2版)
- 笨叔
- 1309字
- 2024-09-23 17:56:02
3.3 加載與存儲指令
和其他RISC體系結(jié)構(gòu)一樣,RISC-V體系結(jié)構(gòu)也基于加載和存儲的體系結(jié)構(gòu)設(shè)計(jì)理念。在這種體系結(jié)構(gòu)下,所有的數(shù)據(jù)處理都需要在通用寄存器中完成,而不能直接在內(nèi)存中完成。因此,要先把待處理數(shù)據(jù)從內(nèi)存加載到通用寄存器,然后進(jìn)行數(shù)據(jù)處理,最后把結(jié)果寫回內(nèi)存中。
1.加載指令
加載指令的格式如下。
l{d|w|h|b}{u} rd, offset(rs1)
其中,相關(guān)選項(xiàng)的含義如下。
● {d|w|h|b}:表示加載的數(shù)據(jù)寬度。加載指令如表3.1所示。
● {u}:可選項(xiàng),表示加載的數(shù)據(jù)為無符號數(shù),即采用零擴(kuò)展方式。如果沒有這個(gè)選項(xiàng),則加載的數(shù)據(jù)為有符號數(shù),即采用符號擴(kuò)展方式。
● rd:表示目標(biāo)寄存器。
● rs1:表示源寄存器1。
● (rs1):表示以rs1寄存器的值為基地址進(jìn)行尋址,簡稱rs1地址。
● offset:表示以源寄存器的值為基地址的偏移量。offset是12位有符號數(shù),取值范圍為[?2048, 2047]。
表3.1 加載指令

上述加載指令的編碼如圖3.3所示,其中opcode字段都是一樣的,唯一不同的是funct3字段。

圖3.3 加載指令的編碼
【例3-2】 下面的代碼使用了加載指令。
1 li t0, 0x80000000
2
3 lb t1, (t0)
4 lb t1, 4(t0)
5 lbu t1, 4(t0)
6 lb t1, -4(t0)
7 ld t1, (t0)
8 ld t1, 16(t0)
第1行是一條偽指令,表示把立即數(shù)加載到t0寄存器中。
在第3行中,從以t0寄存器的值為基地址的內(nèi)存中加載1字節(jié)的數(shù)據(jù)到t1寄存器,并對這1字節(jié)的數(shù)據(jù)進(jìn)行符號擴(kuò)展。符號擴(kuò)展是計(jì)算機(jī)系統(tǒng)把小字節(jié)數(shù)據(jù)轉(zhuǎn)換成大字節(jié)數(shù)據(jù)的規(guī)則之一,它將符號位擴(kuò)展至所需要的位數(shù)。例如,一個(gè)8位的有符號數(shù)為0x8A,它的最高位(第7位)為1,因此在做符號擴(kuò)展的過程中,高字節(jié)部分需要填充為0xFF,如圖3.4所示,符號擴(kuò)展到64位的結(jié)果為0xFFFF FFFF FFFF FF8A。

圖3.4 符號擴(kuò)展
在第4行中,以t0寄存器的值為基地址加上4字節(jié)的偏移量為內(nèi)存地址(0x8000 0004),再從這個(gè)內(nèi)存地址中加載1字節(jié)的數(shù)據(jù)到t1寄存器中,并對該字節(jié)的數(shù)據(jù)進(jìn)行符號擴(kuò)展。
第5行中的指令與第4行中的指令基本類似,不同之處在于該字節(jié)的數(shù)據(jù)不會做符號擴(kuò)展,即按照無符號數(shù)處理,因此高字節(jié)部分填充為0,稱為零擴(kuò)展,如圖3.5所示。

圖3.5 零擴(kuò)展
在第6行中,以t0寄存器的值為基地址減去4字節(jié)的偏移量為內(nèi)存地址(0x7FFF FFFC),再從這個(gè)內(nèi)存地址中加載1字節(jié)的數(shù)據(jù)到t1寄存器中,并對該字節(jié)的數(shù)據(jù)進(jìn)行符號擴(kuò)展。
在第7行中,從以t0寄存器的值為基地址的內(nèi)存中加載8字節(jié)的數(shù)據(jù)到t1寄存器中。
在第8行中,以t0寄存器的值為基地址加上16字節(jié)的偏移量為內(nèi)存地址(0x8000 0010),再從這個(gè)內(nèi)存地址中加載8字節(jié)的數(shù)據(jù)到t1寄存器中。
【例3-3】 下面的代碼使用LUI加載立即數(shù)。
lui t0, 0x80200
lui t1, 0x40200
在第1行中,首先把0x80200左移12位得到0x8020 0000,然后進(jìn)行符號擴(kuò)展,最后結(jié)果為0xFFFF FFFF 8020 0000。
在第2行中,首先把0x40200左移12位得到0x4020 0000,然后進(jìn)行符號擴(kuò)展,因?yàn)樽罡呶粸?,所以最后結(jié)果為0x4020 0000。
【例3-4】 下面的代碼有錯誤。
lb a1, 2048(a0)
lb a1,-2049(a0)
上述指令的偏移量超過了取值范圍,匯編器會報(bào)錯。
AS build_src/boot_s.o
src/boot.S: Assembler messages:
src/boot.S:6: Error: illegal operands 'lb a1,-2049(a0)'
src/boot.S:7: Error: illegal operands 'lb a1,2048(a0)'
make: *** [Makefile:28: build_src/boot_s.o] Error 1
2.存儲指令
存儲指令的格式如下。
s{d|w|h|b} rs2, offset(rs1)
其中,相關(guān)選項(xiàng)的含義如下。
● {d|w|h|b}:表示存儲的數(shù)據(jù)寬度。根據(jù)數(shù)據(jù)的位寬,存儲指令的分類如表3.2所示。
● rs1:表示源寄存器1,用來表示基地址。
● (rs1):表示以rs1寄存器的值為基地址進(jìn)行尋址,簡稱rs1地址。
● rs2:表示源寄存器2,用來表示源操作數(shù)。
● offset:表示以源寄存器的值為基地址的偏移量。offset是12位有符號數(shù),取值范圍為[?2048, 2047]。
表3.2 存儲指令的分類

- 一步一步學(xué)Spring Boot 2:微服務(wù)項(xiàng)目實(shí)戰(zhàn)
- 軟件項(xiàng)目管理(第2版)
- SOA實(shí)踐
- Cross-platform Desktop Application Development:Electron,Node,NW.js,and React
- JavaScript Unlocked
- jQuery開發(fā)基礎(chǔ)教程
- 微信小程序項(xiàng)目開發(fā)實(shí)戰(zhàn)
- Flutter跨平臺開發(fā)入門與實(shí)戰(zhàn)
- Node.js Design Patterns
- Learning R for Geospatial Analysis
- 從零開始學(xué)C#
- Oracle GoldenGate 12c Implementer's Guide
- Unity Android Game Development by Example Beginner's Guide
- Raspberry Pi Blueprints
- Java EE 7 Development with WildFly