-1

学习 RiscV 我的讲师定义了一个名为 Load Upper Immediate (lui) 的新命令,如下所示:

lui rt, imm

将立即数 imm 的下半字加载到寄存器 rt 的上半字。寄存器的低位设置为 0。

带有以下图像:

在此处输入图像描述

但是有几件事我无法理解:

  1. “加载立即数的下半字”这是什么意思?我认为如果我们在 imm 中有 32 位,那么它会加载前 16 位,对吗?

  2. 图像是否正确?前半部分不应该全为零并且定义提到了吗?为什么我们有那些 0xf, 0, rt 以及 rt 是从哪里来的?

  3. 给定以下命令:lui S0, 0x1234
    它将做什么?我不知道内存中位置 1234 的值...

4

3 回答 3

2

图像是否正确?前半部分不应该全为零并且定义提到了吗?为什么我们有那些 0xf, 0, rt 以及 rt 是从哪里来的?

是的,这是正确的;但是,该图像向我们展示了它是 MIPS 指令,而不是 RISC V 1

0xf 是lui. 有一个 5 位(零)的未使用字段和一个寄存器字段以及 16 位立即数。

lui不是内存引用指令——它只是将存储在指令中的常量加载到寄存器中。

给定以下命令: lui S0, 0x1234 它会做什么?

lui s0, 0x1234     ; s0 becomes 0x12340000

您可以在MIPS 绿皮书中查找它。

可以这么说,使用 2 条指令我们可以形成一个 32 位的常量值(数据值或内存地址)。第一条指令lui形成 32 位值的高 16 位,第二条指令使用普通orior提供低 16 位addi

Load Upper Imm.        lui rt,imm      I-Type        R[rt] = {imm, 16’b0}

这一条指令相当于2条指令序列:

ori rt, r0, imm         ; load 16-bit constant
sll rt, rt, 16          ; shift left by 16 bits

脚注 1:这是 RISC V 版本LUI

 31    12 11   7 6       0
+-------------------------+
|  imm   |  rd  |  opcode |
+-------------------------+
    20       5        7

如您所见,完全不同:立即数是 20 位长(不是 MIPS 的 16 位),当然,操作码在右边(7 位而不是 MIPS 的 6 位)。(也没有浪费的零。)

于 2020-12-13T18:39:14.677 回答
1

在尝试阅读或编写汇编语言之前,您需要获取文档。对于您使用的指令集,这是 MIPS 问题(您发布的图像)还是标题文本中记录的 risc-v 问题等?

假设 risc-v 访问 risc-v.org 并点击文档链接,他们已经非常容易找到它。

risc-v 中的 LUI 是这样定义的

33222222222211111111 11
10987654321098765432 10987 6543210
     imm[31:12]        rd   opcode

bits 31:12 of the instruction are the immediate
bits 11:7  of the instruction are the destination register
bits 6:0   of the instruction are the opcode

显然,每条指令都需要一些位供处理器解码以知道它是什么指令,只有一个可以具有模式零,因此大多数操作码中都有非零位。同样,您需要一个目标寄存器,其中值被存储,也被编码在指令中。

LUI(加载上立即数)用于构建 32 位常量并使用 U 型格式。LUI 将 U 立即数放在目标寄存器 rd 的前 20 位,用零填充最低 12 位。

该指令的工作原理非常明显。

我承认 risc-v 文档可以做得更好,找到操作码...0b0110111 或 0x37。

不确定人类如何阅读数字的困惑是什么

0b0110111 = 0x37 = 067 (octal) = 55 (decimal)

这些都描述了相同的值,它们都描述了指令中的相同位模式。

所以这意味着他们可以像其他人一样把它放在指令定义中。

33222222222211111111 11
10987654321098765432 10987 6543210
     imm[31:12]        rd  0110111

所以知道我们可以例如构造

.word 0x12345137

组装然后拆卸

Disassembly of section .text:

00000000 <.text>:
   0:   12345137            lui x2,0x12345

好的,让我们向前尝试:

.word 0x12345137
lui x2,0x12345

组装和拆卸

Disassembly of section .text:

00000000 <.text>:
   0:   12345137            lui x2,0x12345
   4:   12345137            lui x2,0x12345

所以我们开始了,指令编码解决了。

LUI(加载上立即数)用于构建 32 位常量并使用 U 型格式。LUI 将 U 立即数放在目标寄存器 rd 的前 20 位,用零填充最低 12 位。

所以这很清楚 32 位常数在这种情况下

0x12345000

在这种情况下被存储在寄存器 x2 中。

所有指令的编码和操作都定义了,大部分应该很容易理解。编码非常直接且易于理解。

现在,如果这是一个 MIPS 问题而不是 risc-v 问题,那么在这种情况下它同样容易理解。16 位立即数进入常量的 31:16 位,其中 15:0 位全部为零,并且该常量存储在指令中编码的寄存器中。连同操作码一起,处理器可以知道这是什么指令。

于 2020-12-14T01:36:48.230 回答
0

首先,这是 MIPS 的版本lui,而不是 RISC-V。它们是相似的 ISA,但肯定有不同的机器代码和不同大小的立即数。

有关您的部分问题和一些必要背景,请参阅@Erik 的回答,但是是的,图像中的措辞存在问题。

“加载立即数的下半字”这是什么意思?我想如果我们在 imm 中有 32 位,那么它会加载前 16 位,对吗?

这部分图像解释得很糟糕;甚至可以说是错误的。图中的图表显示了整个 32 位指令字及其各个字段。 立即数是指令字的低半字。 “立即数的下半字”整个立即数,没有上半字。以这种方式表述它是零意义的,并且具有高度误导性。

放置在目标寄存器中的值是立即数左移 16,所以是的,立即数放置在 32 位寄存器的高半字中。


给定以下命令:lui S0, 0x1234

在 MARS 中单步执行,看看会发生什么。查看调试器中的寄存器值。是0x1234 << 16

于 2020-12-13T19:12:14.497 回答