"lui a4,%hi(0x0001ff00)" 的意外行为
Unexpected behaviour of "lui a4,%hi(0x0001ff00)"
我在使用 %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
%hi(...)
函数比看起来更聪明。它不只是 return 给定参数的前 20 位。
%hi
预计将在 lui
指令中使用,该指令将很快跟上另一条指令,如 add %lo(...)
,它将通过提供完成寄存器的 32 位加载低 12 位。
在执行add
指令期间,这些低12位将被符号扩展以产生一个32位值,然后将其添加到寄存器的原始内容中。当低 12 位的最高位为 0 时,此符号扩展步骤对寄存器现有的最高 20 位没有影响。但是,当低 12 位的最高位为“1”时,符号扩展具有从寄存器高 20 位的现有值中减一的效果。
在这种情况下,%hi(0x0001ff00)
函数发现低 12 位的最左边位是“1”。因此,它预计将由以下 add %lo(0x0001ff00)
执行的减法,并将 0x00020
写入寄存器的前 20 位。 0x00020
将通过预期的符号扩展 add
.
转换为您想要的 0001f
如果您希望您的程序为所有三个语句生成相同的指令,请给 %hi
一个参数,其低 12 位在最左边的位置为 0。 lui %hi(0x0001f700)
之类的东西就可以了。
总而言之,如果与“%lo()”返回的带符号值一起使用,“%hi()”宏将采用带符号的 int 值。
我什至不认为 "lui" 指令是假定的,这可能是任何其他取立即值的指令。这是您在示例中使用的内容,但还有许多其他使用立即数参数的 RV 指令
所以应该有另一种形式,如“%hu()”,与“%lu()”一起使用,不假设低位部分的符号扩展,甚至不假设“%lu( )”将被使用
我在使用 %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
%hi(...)
函数比看起来更聪明。它不只是 return 给定参数的前 20 位。
%hi
预计将在 lui
指令中使用,该指令将很快跟上另一条指令,如 add %lo(...)
,它将通过提供完成寄存器的 32 位加载低 12 位。
在执行add
指令期间,这些低12位将被符号扩展以产生一个32位值,然后将其添加到寄存器的原始内容中。当低 12 位的最高位为 0 时,此符号扩展步骤对寄存器现有的最高 20 位没有影响。但是,当低 12 位的最高位为“1”时,符号扩展具有从寄存器高 20 位的现有值中减一的效果。
在这种情况下,%hi(0x0001ff00)
函数发现低 12 位的最左边位是“1”。因此,它预计将由以下 add %lo(0x0001ff00)
执行的减法,并将 0x00020
写入寄存器的前 20 位。 0x00020
将通过预期的符号扩展 add
.
0001f
如果您希望您的程序为所有三个语句生成相同的指令,请给 %hi
一个参数,其低 12 位在最左边的位置为 0。 lui %hi(0x0001f700)
之类的东西就可以了。
总而言之,如果与“%lo()”返回的带符号值一起使用,“%hi()”宏将采用带符号的 int 值。
我什至不认为 "lui" 指令是假定的,这可能是任何其他取立即值的指令。这是您在示例中使用的内容,但还有许多其他使用立即数参数的 RV 指令
所以应该有另一种形式,如“%hu()”,与“%lu()”一起使用,不假设低位部分的符号扩展,甚至不假设“%lu( )”将被使用