【问题标题】:Is there a way to assign a floating point immediate to a register有没有办法将浮点立即分配给寄存器
【发布时间】:2021-11-07 15:44:54
【问题描述】:

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

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

【问题讨论】:

  • 什么指令集以及指令集文档对此有何评论?
  • 我想你的意思是movsdmovq。唯一的movsq 是可以与rep 一起使用的字符串指令。但无论如何,不​​幸的是 x86 没有适用于 x87 或 SSE2/AVX/AVX-512 的 mov-immediate。 (ARM 可以,使用少量立即数位,可让您构造一些常见的整数 FP 值,如 2.0 或 0.5)
  • 原则上,您可以将编码浮点/双精度的 32 位或 64 位立即数移动到整数寄存器中,然后将 movdmovq 移动到 SSE 寄存器中。但听起来你真正想要的根本不是立即数——你希望你的数字在内存中,但你不想让相同的值占用内存两次。那种常量合并去重通常由编译器完成,或者可能是一个非常花哨的链接器,但我认为它可能超出了汇编器的能力。

标签: assembly x86 floating-point nasm


【解决方案1】:

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

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

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”不同(假设您可以在%define 中使用字符串连接来构造可以测试的%define VALUE_1.0_USED稍后使用%ifndef,并假设预处理器可以灵活地接受宏名称中的字符)您需要关于宏参数格式的严格规则;和简单的表达式(例如fld_macro 2.0/1.0%define CHICKENS_PER_GOOSE 5 然后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] 之类的操作以避免负载。

【讨论】:

    【解决方案2】:

    在 NASM 中,您不能直接这样做。您可能想使用 EQU:

    half EQU 0.5
    

    但是您不能这样做,因为 EQU 的 NASM 不支持浮点常量。您应该手动将浮点转换为十六进制(或者更有可能使用程序):

    half EQU 0x3fe0000000000000
         mov RAX, half
    

    另一种选择是使用 dq(它确实支持浮点),但这需要从内存中加载常量,我觉得你不想避免这种情况。

    【讨论】:

      猜你喜欢
      • 2013-07-22
      • 2013-06-27
      • 2012-04-24
      • 2023-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多