0

I am trying to write a C++ code for conversion of assembly dq 3FA999999999999Ah into C++ double. What to type inside asm block? I dont know how to take out the value.

int main()
{
    double x;

    asm
    {
        dq  3FA999999999999Ah
        mov x,?????
    }

    std::cout<<x<<std::endl;

    return 0;
}
barej
  • 1,330
  • 3
  • 25
  • 56
  • 2
    Is your goal simply to assign the specified hex value to a double? If so, there are much easier ways (namely a reinterpret_cast or a unioned struct). Actually, it might even be possible to assign a hex literal straight to a double. Not familiar with the standard in that regard :). – Corbin Aug 01 '15 at 03:25
  • Which compiler are you using? – bendervader Aug 01 '15 at 03:32
  • gcc compiler (g++). in Linux – barej Aug 01 '15 at 03:32
  • http://stackoverflow.com/questions/8511676/portable-data-reinterpretation might be relevant, though it's C and not C++. I'm not confident enough in my knowledge of this to know for sure that this is correct, but I believe the most portable approach is the union approach with something like http://cpp.sh/4ufk. – Corbin Aug 01 '15 at 03:39
  • 1
    It also might be worth noting that you're going to need to consider endianness if you do this. For example, if the hex literal you specified is the value for `x`, on a machine of different endianness, it could be something completely different -- like completely and entirely different in terms of the number it represents. – Corbin Aug 01 '15 at 03:44

1 Answers1

2

From the comments it sounds a lot like you want to use a reinterpret cast here. Essentially what this does is to tell the compiler to treat the sequence of bits as if it were of the type that it was casted to but it doesn't do any attempt to convert the value.

uint64_t raw = 0x3FA999999999999A;
double x = reinterpret_cast<double&>(raw);

See this in action here: http://coliru.stacked-crooked.com/a/37aec366eabf1da7

Note that I've used the specific 64bit integer type here to make sure the bit representation required matches that of the 64bit double. Also the cast has to be to double& because of the C++ rules forbidding the plain cast to double. This is because reinterpret cast deals with memory and not type conversions, for more details see this question: Why doesn't this reinterpret_cast compile?. Additionally you need to be sure that the representation of the 64 bit unsigned here will match up with the bit reinterpretation of the double for this to work properly.

EDIT: Something worth noting is that the compiler warns about this breaking strict aliasing rules. The quick summary is that more than one value refers to the same place in memory now and the compiler might not be able to tell which variables are changed if the change occurs via the other way it can be accessed. In general you don't want to ignore this, I'd highly recommend reading the following article on strict aliasing to get to know why this is an issue. So while the intent of the code might be a little less clear you might find a better solution is to use memcpy to avoid the aliasing problems:

#include <iostream>

int main()
{
    double x;
    const uint64_t raw = 0x3FA999999999999A;
    std::memcpy(&x, &raw, sizeof raw); 
    std::cout<<x<<std::endl;

    return 0;
}

See this in action here: http://coliru.stacked-crooked.com/a/5b738874e83e896a

This avoids the issue with the aliasing issue because x is now a double with the correct constituent bits but because of the memcpy usage it is not at the same memory location as the original 64 bit int that was used to represent the bit pattern needed to create it. Because memcpy is treating the variable as if it were an array of char you still need to make sure you get any endianness considerations correct.

Community
  • 1
  • 1
shuttle87
  • 15,466
  • 11
  • 77
  • 106