0

I know that it isn't possible to load an immediate value directly into a register in x64 assembly. I do know, however, that we can declare a global variable in the .data segment of a program, then load that value into a register. What I'm curious about, on the other hand, is the possibility of storing these values as local variables to a function on the stack (just like we can for word-sized integers). I'm writing a small compiler with a desire to support floating-point values, and would rather not have to write all variables out to global static memory (but I suppose I can if that's the only way).

fuz
  • 88,405
  • 25
  • 200
  • 352
  • 2
    Floating point instructions can take any kind of memory operand, including memory operands referring to the stack. I don't quite understand what the problem is. Note that loading floating point constants from the data segment will perform better than first storing them on the stack and then loading them from there. Also clarify if you want to use the SSE or the x87 floating point unit. The two differ in what options you have. – fuz Dec 11 '22 at 02:25
  • 3
    You can of course push or `mov` immediate data to stack memory. You can even `movabs $imm64, %rdx` / `movq %rdx, %xmm0` to get a 64-bit immediate into XMM0 as a scalar double (binary64) bit pattern. – Peter Cordes Dec 11 '22 at 02:27
  • @fuz Let's say I want to store a variable `x' with the value 7 on the stack frame of the main function. Obviously, I would make space for eight bytes on the stack and move 7 into the appropriate location. I'd like to be able to do the same thing with floating point values, e.g., storing 7.25 on the stack. – TheSinisterStone Dec 11 '22 at 02:27
  • @PeterCordes I think `movabs $imm64, ...` is just what I'm looking for! – TheSinisterStone Dec 11 '22 at 02:28
  • Are you asking how to get the assembler to let you write `7.25` in the as source, and have it encode that into a floating-point bit-pattern for you, instead of having to write `push $0x40e80000` / `flds (%esp)`? (https://www.h-schmidt.net/FloatConverter/IEEE754.html). GAS probably doesn't have that, but NASM does, `mov rdx, __?float64?__(7.25)` [Use of NASM's \_\_?float?\_\_ macros](https://stackoverflow.com/q/66476230) – Peter Cordes Dec 11 '22 at 02:29
  • @PeterCordes That's kind of what I'm after, yes. Is `movabs` only immediate-to-register or is it also immediate-to-memory? It doesn't really matter if it's the former since I can just do, e.g., `movabs $7.5, %xmm0` followed by `movq %xmm0, -8(%rbp)`. Though, using `movabs` directly, like this, produces an operand mismatch error. – TheSinisterStone Dec 11 '22 at 02:33
  • No, `movabs` in AT&T syntax requires an integer operand; the assembler won't encode a float for you. x86-64 can't move a 64-bit immediate to memory, only to an integer register. [why we can't move a 64-bit immediate value to memory?](https://stackoverflow.com/q/62771323) / [Difference between movq and movabsq in x86-64](https://stackoverflow.com/q/40315803) (Not an FP/SIMD register like XMM0; I thought you wanted the FP data in an FP register, so why would you store XMM0 to stack memory?) – Peter Cordes Dec 11 '22 at 02:35
  • If you're asking about 64-bit code, you should probably tag the question x86-64. In that case, the normal way to do scalar floating point math is with XMM registers, like `addsd %xmm0, %xmm1`. – Peter Cordes Dec 11 '22 at 02:39

0 Answers0