首页 > 解决方案 > 有没有办法将浮点立即分配给寄存器

问题描述

据我所知,不可能使用一条指令直接在寄存器中移动浮点数,如下所示:

fld 0.5

或者

movsd xmm0 , 0.4 

我想制作一个宏,将浮点值存储到内存中,然后存储到寄存器中,如下所示:

%macro fld_macro 1  

section .data 

_%1 : dq %1

section .text 

fld qword [_%1]

%endmacro 

我的问题是我想在执行宏之前先检查该值是否已经存在。类似于以下内容:

%macro fld_macro 1  

(if _%1 doesnt exist   , then )

section .data 

_%1 : dq %1

section .text 

fld qword [_%1]

(else )

%endmacro 

那可能吗?我正在使用 nasm (-fwin64 ) 和 gcc

标签: assemblyx86floating-pointnasm

解决方案


据我所知,不可能像这样使用一条指令直接在寄存器中移动浮点数

对于大多数值,这是不可能的。

80x86 FPU 确实支持在单个指令中加载一些常用常量(+0.0、+1.0、PI、...)(没有任何立即数)。您可以在手册中查看完整列表及其详细信息(或在此处:https ://www.felixcloutier.com/x86/fld1:fldl2t:fldl2e:fldpi:fldlg2:fldln2:fldz )。

id 喜欢制作一个 makro,将浮点值存储到内存中,然后存储到寄存器中,如下所示:

我的问题是我想在执行宏之前先检查该值是否已经存在。像下面这样的东西

我认为你不能;至少不是以稳健的方式。问题是预处理器在字符串上工作,并且(例如)字符串“1.0”与字符串“1.00”不同(假设您可以在 a 中使用字符串连接%define来构造%define VALUE_1.0_USED可以稍后测试的 a %ifndef,并假设预处理器可以灵活地接受宏名称中的字符)您需要对宏参数的格式有严格的规定;和简单的表达式(例如fld_macro 2.0/1.0or %define CHICKENS_PER_GOOSE 5then fld_macro CHICKENS_PER_GOOSE * 5.0)会破坏一切。

为了获得极大的灵活性,您可以编写自己的“重新处理器”——例如,告诉汇编程序只进行预处理,然后将结果输入您用 C 编写的实用程序,然后告诉汇编程序汇编您的实用程序的输出。在这种情况下,您的宏可以扩展fld_macro CHICKENS_PER_GOOSE * 5.0**** 25.0(它不需要是有效的程序集)并且您的实用程序可以忽略不以您的特殊****标记开头的所有内容,然后解析该值并将其替换为适当的值(一个fldpi或数据部分中的新常量或重新使用数据部分中的现有常量,如果您检测到没有精度损失,则使用 32 位浮点加载等)。

最简单的选择是停止使用宏并自己动手;喜欢:

    section .data
CONST1_25:                   dq 1.25
CONST_CHICKENS_PER_GOOSEx5:  dq CHICKENS_PER_GOOSE * 5.0
...

    section .text
    fld qword [CONST_CHICKENS_PER_GOOSEx5]

这正是我要做的;因为在实际代码中,大多数负载根本不存在。真正的问题是您想要做类似的事情fmul qword [CONST1_25]fadd qword [CONST_CHICKENS_PER_GOOSEx5]避免负载。


推荐阅读