使用 NASM 的 __?float?__ 宏



NASM手册讨论了这些宏,但据我所知,它并没有真正解释如何使用它们。第3.4.6节声明:

浮点常量只能作为DBDWDDDQDTDO的参数,或者作为特殊运算符__?float8?____?float16?____?bfloat16?____?float32?____?float64?____?float80m?____?float80e?____?float128l?____?float128h?__的参数

起初,我认为这是在数据部分之外使用浮点常量。但是当我尝试mov xmm0, __?float32?__(1.23)时,我得到了一个"无效的操作码和操作数组合";错误。最终,我看到foo: dd __?float32?__(1.23)是有效的。但我觉得这很奇怪;如果你可以直接做dd 1.23,这些宏的意义是什么?一种可能是,例如,您需要在四字中定义一个单精度浮点数。这真的是这些宏的唯一用途吗,还是我用错了?

这些宏并没有改变x86没有直接源和XMM或x87目标指令的事实。请记住,NASM是一个汇编器,而不是编译器。

用例包括您想要立即将FP位模式移动到整数寄存器的罕见情况,如mov eax, __?float32?__(1.23)。之后,您可以执行movd xmm0, eax,甚至AVX-512vpbroadcastd xmm0, eax

通常编译器从内存中的常量中加载FP数据到寄存器中(这通常是一个很好的选择),但这不是唯一的方法。

(AVX-512使立即更有吸引力,因为有效的广播,但你也可以从内存广播只有AVX1,或SSE3movddup的双。编译器仍然为标量浮点数使用内存常量,这仍然是我通常推荐的,除非分析显示大量的数据缓存丢失,并且通常在您的程序中没有很多I-cache丢失。

或者像if (x) *fp_ptr = 1.0;这样的东西,你可能想要像mov dword [rdi], __?float32?__(1.0)那样立即移动到内存中。

另一个用例可能是在NASM%if条件汇编指令中,或者在您希望FP位模式作为不是dd的整数值的其他情况下。尽管没有什么明智的想法。

或者作为表达式的一部分,如__?float32?__(1.0) >> 23,以获得您想要使用的浮点常数的指数(和符号位)。


记录:

mov eax, __?float32?__(1.23)
mov eax, __?float32?__(1.0) >> 23
mov dword [rdi], __?float32?__(1.0)

nasm -felf64 foo.asm组装,用objdump -drwC -Mintel foo.o拆卸

0:   b8 a4 70 9d 3f          mov    eax,0x3f9d70a4
5:   b8 7f 00 00 00          mov    eax,0x7f
a:   c7 07 00 00 80 3f       mov    DWORD PTR [rdi],0x3f800000
相关:

  • NASM:为什么__float32__(1.5)必须用于浮点量而不是1.5?- NASM对dd/dq使用不同的解析器,在数字中看到.意味着浮点数。这就是为什么dd 1.5工作,mov eax, 1.5不(尚未)。

旧的NASM文档__float32__(1.23);仍然可以组装,但是NASM手册目前只记录了这个答案中使用的?表单。我认为这使得它不是一个有效的NASM预处理器宏/令牌,如果这是相关的。并且不是一个有效的符号名。

相关内容

  • 没有找到相关文章

最新更新