assembly 如何将浮点常量移入FP寄存器?

kh212irz  于 2023-01-13  发布在  其他
关注(0)|答案(2)|浏览(118)

所以,我使用A64指令集在汇编形式的ARM中编程。我使用指令fmov d1,#31.0将值移动到dx寄存器。但是,当我使用0.0或任何高于31.0的值时,它显示错误:

"Error: invalid floating-point constant at operand 2 -- `fmov d1,#32.0'"

那么,如何在A64上定义浮点常量?为什么不能使用大于31的值或0?如何用十六进制表示这些值?
另一个问题是:根据arm's website,它支持使用浮点寄存器作为Bx,Hx,Sx,Dx和Qx(分别为8,16,34,64和128位),但我只是不能使用Bx,Hx和Qx寄存器,它显示:
"错误:操作数不匹配--'fmov b1,#1.0'"
"错误:所选处理器不支持'fmov h1,#2.0"
"错误:操作数不匹配--'fmov q1,#2.0'"
如何正确设置第二个操作数?

rvpgvaaj

rvpgvaaj1#

只有一小部分浮点常量可以和fmov一起使用,因为常量在指令中被编码为8位立即数。具体来说,它必须可以表示为±n/16×2r,其中 n 是一个整数,范围是16 ≤ n ≤ 31,r 是一个整数,范围是-3 ≤ n ≤ 4。

  • ARMv 8架构参考手册中提供了支持的数字的准确列表。* 此外,fmov仅适用于16、32和64位数据大小,因为ARMv 8未指定8位或128位浮点格式。对于不支持FEAT_FP16的ARMv 8内核,也不支持16 bit的数据大小,ARMv 8在很多地方都缺乏正交性;并非所有指令都可用于所有操作数大小。

另一个简单的解决方案是,使用ldr和文本池中的常量(需要手动转换为整数)。例如,要加载32.0,请将32.0转换为IEEE 754表示形式,得到0x4040000000000000。然后可以按如下方式加载此常量:

ldr d1, =0x4040000000000000

使用SIMD和FP寄存器且值位于文字池中的ldr指令提供32位、64位和128位的操作数大小。较小的操作数大小不适用于文字池寻址模式。如果要加载8位或16位寄存器,请加载相应的32位寄存器。
一个稍微快一点的解决方案是首先将所需的数字加载到通用寄存器(支持更灵活的立即数生成),然后将其移动到SIMD和FP寄存器:

mov x0, #0x4040000000000000
fmov d1, x0

要加载0.0或掩码,请使用movi指令。此指令的法律的立即数集取决于操作数大小。但对于您的情况,这只是

movi d1, #0

这会清除d1寄存器(从而也会清除b1h1s1q1寄存器)。

hfyxw5xn

hfyxw5xn2#

我已经迟到了,但是我(一个业余爱好者)找到了如何使用. data将浮点数加载到寄存器中。下面是我打印PI的示例代码。我希望它能帮助其他人,因为我自己花了大约两个小时试图找到它。-- Jds

.global main
.align 4

main:
    ADRP    X1, pi@PAGE         // Load the address for our "pi" data
    ADD X1, X1, pi@PAGEOFF
    LDR D1, [X1]                // Store the contents of X1 to D1

    STR D1, [SP, #-16]!         // Store the float (D1) onto the stack for printing
    ADRP    X0, format@PAGE     // Load the address of our printf format string
    ADD X0, X0, format@PAGEOFF

    
end:
    BL  _printf                 // print -- reads string from X0 and data from stack
    mov X16, #1
    svc 0


.data
    pi: .double 3.141519
    format: .asciz  "Pi is %f \n"

相关问题