0

I can save a float into a 32 bit register with the following command:

mov ebx,__?float32?__(1.23)
movd xmm1,ebx  ; works

However when I try the following code, I get an error:

mov bx,__?float16?__(1.23)
movd xmm1,bx   ; /tmp/SASM/program.asm:9: error: invalid combination of opcode and operands

How can I use mov to save a 8.8 float into a 16- bit register? Or is there some other way to do so?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
HeapUnderStop
  • 378
  • 1
  • 9
  • 1
    You can always do the conversion yourself if all else fails. – Jester Nov 02 '22 at 14:45
  • 5
    "fixed point float" sounds like an oxymoron... – Dan Mašek Nov 02 '22 at 14:46
  • Do you *actually* want to use 8.8 fixed-point? If so, you shouldn't be using `__?float16?__`, because that's IEEE754 binary16 half-precision **floating** point, with exponent and mantissa fields. https://en.wikipedia.org/wiki/Half-precision_floating-point_format (usable in XMM registers only with F16C conversion, or with [AVX-512FP16](https://en.wikipedia.org/wiki/AVX-512#FP16) in Sapphire Rapids and hacked Alder Lake-AVX512 ([Half-precision floating-point arithmetic on Intel chips](https://stackoverflow.com/q/49995594)). – Peter Cordes Nov 02 '22 at 20:25
  • `movd xmm1, ebx` works, it requires a 32-bit source reg, which includes the low 16 bits you set with `mov bx, imm16`. To make sure those upper bits are zero, you should `mov ebx, imm32` with your 16-bit constant; that avoids partial-register penalties anyway. [Why doesn't GCC use partial registers?](https://stackoverflow.com/q/41573502) . (If you have AVX-512FP16, you'd also have `vpbroadcastw ymm1, bx` from AVX-512BW https://www.felixcloutier.com/x86/vpbroadcastb:vpbroadcastw:vpbroadcastd:vpbroadcastq.) – Peter Cordes Nov 02 '22 at 20:29

1 Answers1

2

Fixed point values have an implied shift value.

To save an 8.8 fixed point value in a register in NASM you'd have to do the implied shift yourself; like maybe mov ebx,320 ;1.25 << 8 = 320.

Note: Based on this stackoverflow question I don't think there's a way to convert the result of a floating point constant expression into an integer when assembling in NASM, so something cleaner (like a hypothetical mov ebx, __?int32?__ (1.25 << 8)) won't work.

Brendan
  • 35,656
  • 2
  • 39
  • 66
  • You could write `(125 << 8) / 100`, so you have 1.25 as 125/100, but then you reorder that with the left shift so everything is integer the whole time without losing any bits. (In this case the division is exact. In an inexact case, like `(123<<8) / 100`, you'd get truncation toward 0. You'd get integer 314 instead of 314.88, so a fixed-point 0x13a that represents 1 + 58/256 = 1.2265625. – Peter Cordes Nov 02 '22 at 20:21