5

I'm working with Intel x64 assembly, NASM compiler, trying to move the "0x4000000000000000" constant to memory, which in the ieee 754 standard double should be equal to 2.0.

The code I'm using is:

%define two 0x4000000000000000 

section .text

foo:

push rbp
mov rbp, rsp

mov QWORD [rdi], two

pop rbp
ret

Compiling this throws

warning: signed dword immediate exceeds bounds.

When i print the value in C++ it shows "0" instead of "2".

I've already found a way of getting the right value, which is:

mov r9, 0x4000000000000000
mov [rdi], r9

But i would like to know if there is a way of achieving this without the use of a register.

by the way, im compiling the code with this script:

#!/bin/bash
nasm -f elf64 -g -F dwarf vvp_asm.asm -o vvp_asm.o
g++ -c -m64 -std=c++11 main.cpp -o main.o
g++ -o main -m64 vvp_asm.o main.o
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Martin Ventura
  • 167
  • 1
  • 3
  • 14
  • 1
    That is the recommended way, but if you absolutely insist on avoiding a register, you can store it in two halves of course. – Jester Sep 24 '17 at 23:06
  • Possible duplicate of [Difference between movq and movabsq in x86-64](https://stackoverflow.com/questions/40315803/difference-between-movq-and-movabsq-in-x86-64) – phuclv Jul 04 '18 at 04:23

1 Answers1

11

There is no instruction

    mov r/m64, imm64

You could use

    mov dword [rdi], 0
    mov dword [rdi+4], 0x40000000

or

    and qword [rdi], 0
    mov byte [rdi+7], 0x40

which is only 8 bytes (if that matters).

prl
  • 11,716
  • 2
  • 13
  • 31
  • You left off the `byte` size specifier in the last version. You *could* use `and r/m64, imm8` if optimizing for code-size, but that would suck for performance. It's only a couple more bytes to `mov qword [rdi], 0` / `mov byte [rdi+7], 0x40` (and that's smaller than your first option, but about the same speed). – Peter Cordes Sep 25 '17 at 00:05
  • Any multi-part option will produce a store-forwarding stall if you do a 64-bit load right away, unlike `mov r64, imm64` / `mov r/m64, r64`. You'd think it would be more efficient to do something like `mov eax, 1`, `shl rax, 40` or `xor eax,eax`/`bts rax, 40` instead of a 10-byte mov imm64, but there's barely any saving in code-size. – Peter Cordes Sep 25 '17 at 00:08