我对%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
答案 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()”将被使用