assembly 使用NASM的__?float?__宏

c0vxltue  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(170)

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,那么这些宏的意义何在?一种可能性是,例如,您可能需要定义四字中的单精度浮点数。这真的是这些宏的唯一用途吗?还是我用错了它们?

cl25kdpy

cl25kdpy1#

这些宏并不能改变x86没有直接源代码和XMM或x87目标代码的指令的事实。
这些用例包括极少数情况,即您希望立即将FP位模式移入整数寄存器,如**mov eax, __?float32?__(1.23)**。之后您可能会执行movd xmm0, eax,甚至AVX-512 vpbroadcastd xmm0, eax
通常,编译器将FP数据从内存中的常量加载到寄存器中(这通常是一个很好的选择),但这不是唯一的方法。
(AVX-512使立即数更有吸引力,因为它的广播效率更高,但您也可以使用AVX 1或SSE 3 movddup从内存广播double。编译器仍然使用内存常量来实现标量浮点,通常我还是建议这样做,除非性能分析显示大量数据缓存未命中,而通常程序中的指令缓存未命中并不多。)
或者,对于if (x) *fp_ptr = 1.0;这样的代码,您可能希望像mov dword [rdi], __?float32?__(1.0)这样将mov-immediate移到内存中。
另一个用例可能是在NASM %if conditional assembly directive中,或者其他一些情况下,你希望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.23);仍然可以汇编,但是NASM手册目前只记录了这个答案中使用的?形式。我认为这使得它不是一个有效的NASM预处理器宏/令牌,如果这是相关的。并且不是一个有效的符号名称。

相关问题