NASM手册谈到了这些宏,但就我所知,它并没有真正解释如何使用它们。第3.4.6节规定:
浮点常量只能作为DB
、DW
、DD
、DQ
、DT
和DO
的参数,或者作为特殊运算符__?float8?__
、__?float16?__
、__?bfloat16?__
、__?float32?__
、__?float64?__
、__?float80m?__
、__?float80e?__
、__?float128l?__
的参数。和__?float128h?__
的值
一开始,我以为这是在数据部分之外使用浮点常量。但是当我尝试mov xmm0, __?float32?__(1.23)
时,我得到了“操作码和操作数的无效组合”错误。最终,我发现foo: dd __?float32?__(1.23)
可以工作。尽管这让我感到奇怪;如果可以直接执行dd 1.23
,那么这些宏的意义何在?一种可能性是,例如,您可能需要定义四字中的单精度浮点数。这真的是这些宏的唯一用途吗?还是我用错了它们?
1条答案
按热度按时间cl25kdpy1#
这些宏并不能改变x86没有直接源代码和XMM或x87目标代码的指令的事实。
这些用例包括极少数情况,即您希望立即将FP位模式移入整数寄存器,如**
mov eax, __?float32?__(1.23)
**。之后您可能会执行movd xmm0, eax
,甚至AVX-512vpbroadcastd 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
这样的表达式的一部分,以获取要用于某项操作的浮点常量的指数(和符号位)。记录在案:
用
nasm -felf64 foo.asm
组装,用objdump -drwC -Mintel foo.o
拆卸相关:
dd
/dq
使用了不同的解析器,在一个数字中看到.
意味着浮点。这就是为什么dd 1.5
可以工作,而mov eax, 1.5
还不能。旧的NASM记录
__float32__(1.23)
;仍然可以汇编,但是NASM手册目前只记录了这个答案中使用的?
形式。我认为这使得它不是一个有效的NASM预处理器宏/令牌,如果这是相关的。并且不是一个有效的符号名称。