assembly 李指令

z18hc3ub  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(158)

在RISCV汇编中,“li”是伪指令。我有这个指示:

li      t2, 0x1800
csrc    mstatus, t2

“li”被组装成以下2个指令。

lui x7 2
addi x7 x7 -2048

我的问题是,为什么是2和-2048?为什么“离”会组合成“律”和“增”?这种行为有文件规定吗?
我使用“riscv 64-unknown-elf-as”作为汇编程序。

g6baxovj

g6baxovj1#

这种行为有文件规定吗?
这不是真正考虑的行为,而是一个聪明但众所周知的代码序列,用于缩短汇编器和编译器使用的立即数的合成。
处理器的唯一行为是所有I型指令中的12位立即数的符号扩展。
设计师这样做的原因是两件事的结合:

  • 他们希望允许像addi这样的指令的负立即数,以及lwsw认为负偏移量足够有用,因为它们可以用于帧指针相对算术来访问局部变量,或者到达紧接在块之前的块的头部,等等。
  • 此外,他们希望硬件只有一种12位扩展,即有符号扩展。

这两点合在一起意味着lui和以下之一:addilwsw可以完成完整的32位地址/值,所有工作方式相同:第二指令的符号扩展可能需要递增用于lui的常数。
他们不需要这样设计例如,它们可以提供另一条指令addui,该指令在加法之前清除高20位;或者,他们可能已经提供了lwsw的版本来做同样的事情,或者定义了lwsw来只支持12位无符号立即数。
但他们选择的是一种折衷方案,既允许一般的负立即数,也允许硬件中更简单的一种。
设计人员已经在一定程度上简化了硬件,同时考虑了嵌入式和其他功率/尺寸受限的处理器
为什么是2和-2048?
为了避免addi的符号扩展特性,你必须将立即数限制为11位无符号,这将使第12位(符号位)为零,因此在12位中不会为负,所以永远不会扩展负号。例如,0x 400适合11位,因此我们可以这样做:

lui x7, 1
addi x7, x7, 0x400
addi x7, x7, 0x400

实现0x 1000 + 0x 400 + 0x 400 = 0x 1800。
但是,正如你所看到的,这涉及到三个指令!
为了缩短代码序列,我们必须利用额外的第12位(符号),即使它将被设置为/on/true/1/negative,并且将导致addi使用前立即数的高20位的值为-1。
该-1(由12位立即数的符号扩展引起的高20位)需要偏移+1(高20位)以获得所需的数字,并且该+1偏移在lui指令中完成,因此lui x7, 2而不是1,并且addi x7, x7, 0x800完成2指令序列。0x 800作为有符号的12位数是-2048,因此:2和-2048。

相关问题