“ lui a4,%hi(0x0001ff00)”的异常行为

时间:2018-11-19 16:53:24

标签: compiler-errors cross-compiling gnu riscv

我对%hi()汇编器函数有疑问。 此问题特定于RISC-V GNU汇编器。编译程序:

lui     a4,%hi(0x0001ff00)     # Does not give what I expect
lui     a4,0x1f                #
.word   0x0001f737             #

使用

riscv32-unknown-elf-as  -o strange_lui.o strange_lui.s
riscv32-unknown-elf-objdump -D strange_lui.o 

给予

strange_lui.o:     file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0:  00020737            lui a4,0x20
4:  0001f737            lui a4,0x1f
8:  0001f737            lui a4,0x1f

我会认为这三行应该编译为相同的代码。那我在这里想念什么?我正在使用:

riscv32-unknown-elf-as  -v
GNU assembler version 2.31.1 (riscv32-unknown-elf) using BFD version (GNU Binutils) 2.31.1

2 个答案:

答案 0 :(得分:0)

%hi(...)函数看起来比它聪明。它不只是返回给定参数的前20位。

%hi预期将在lui指令中使用,不久之后将跟另一条指令add %lo(...)一起使用,该指令将通过提供低位来完成寄存器的32位加载12位。

在执行add指令期间,低12位将被符号扩展以产生32位值,然后将其添加到寄存器的原始内容中。当低位12的高位为0时,此符号扩展步骤对寄存器的现有高20位没有影响。但是,当低12位的高位为1时,符号扩展名的作用是从寄存器的高20位的现有值中减去1。

在这种情况下,%hi(0x0001ff00)函数看到低位12的最左位为'1'。因此,它预期将由后面的add %lo(0x0001ff00)执行减法,并将0x00020写入寄存器的高20位。该0x00020将通过预期的符号扩展0001f转换为您想要的add

如果希望程序为所有三个语句生成相同的指令,请给%hi一个参数,该参数的低12位在其最左位置为0。像lui %hi(0x0001f700)这样的东西。

答案 1 :(得分:0)

总而言之,如果“%hi()”宏与“%lo()”返回的带符号的值一起使用,则假定带符号的int值。

我什至都不认为“ lui”指令是假定的,这可以是任何其他采用立即值的指令。这就是您在样本中使用的内容,但是还有许多其他使用即时参数的RV指令

因此,应该有另一种形式,例如“%hu()”,与“%lu()”一起使用,不要假设该符号扩展到最下部,甚至不假设“%lu()”将被使用