简体   繁体   中英

Is there a way to assign a floating point immediate to a register

As far as I know, it is not possible to move a floating point number directly in a register using a single instruction, like so:

fld 0.5

or

movsd xmm0 , 0.4 

I'd like to make a macro storing a floating point value to memory and then to the register, like this:

%macro fld_macro 1  

section .data 

_%1 : dq %1

section .text 

fld qword [_%1]

%endmacro 

My issue is that I want to first check if the value already exists before I execute the macro. Something along the lines of:

%macro fld_macro 1  

(if _%1 doesnt exist   , then )

section .data 

_%1 : dq %1

section .text 

fld qword [_%1]

(else )

%endmacro 

Is that possible?

As far as i know , it is not possible to move a floating point number directly in a register using a single instruction , like so

For most values, it's not possible.

The 80x86 FPU does have support for loading some common constants (+0.0, +1.0, PI, ...) in a single instruction (without any immediate). You can see the full list and their details in the manual (or here: https://www.felixcloutier.com/x86/fld1:fldl2t:fldl2e:fldpi:fldlg2:fldln2:fldz ).

id like to make a makro storing a floating point value to memory and then to the register , like this :

my issue is that i want to first check if the value already exists before i execute the macro . something like bellow

I don't think you can; at least not in a robust manner. The problem is that the preprocessor works on strings, and (eg) the string "1.0" is different to the string "1.00" so (assuming you can use string concatenation in a %define to construct a %define VALUE_1.0_USED that can be tested with an %ifndef later, and assuming the preprocessor is flexible in accepting characters in macro names) you'd need strict rules about the formatting of macro parameters; and simple expressions (eg fld_macro 2.0/1.0 or %define CHICKENS_PER_GOOSE 5 then fld_macro CHICKENS_PER_GOOSE * 5.0 ) would break everything.

For extreme flexibility, you could write your own "re-processor" - eg tell the assembler to preprocess only, then feed the result into a utility you wrote in C, then tell the assembler to assemble the output of your utility. In that case, your macro that could expand fld_macro CHICKENS_PER_GOOSE * 5.0 into **** 25.0 (it doesn't need to be valid assembly) and your utility can ignore everything that doesn't start with your special **** marker, then parse the value and replace it with whatever is appropriate (an fldpi or a new constant in the data section or re-using an existing constant in the data section, using a 32-bit floating point load if you detect there'd be no precision loss, etc).

The easiest alternative would be to just stop using macros and do it yourself; like:

    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]

This is exactly what I'd do; because in real code most of the loads simply don't exist. The real problem is that you want to do things like fmul qword [CONST1_25] and fadd qword [CONST_CHICKENS_PER_GOOSEx5] to avoid having a load.

In NASM, you can't do that directly . You might want to use EQU:

half EQU 0.5

But you can't do that because floating point constants for EQU aren't supported by NASM. You could instead do this floating point conversion to hex by hand (or program):

half EQU 0x3fe0000000000000
     mov RAX, half

Another alternative is to use dq but that requires loading the constant from memory and I sense you wan't to avoid that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM