Reputation:
I'm creating a very limited, domain-specific x86 assembler in C++ (Visual Studio 2010) that dynamically generates instructions, writes it to memory, and executes it, all at runtime. First I write them to a temporary byte stream, and then write the entire stream to executable memory in one memcpy
.
I use the following code for constructing a movsd [imm32], xmm1
instruction:
typedef unsigned char byte;
enum SSE2Register;
void WriteValueToMemory(double* dest, SSE2Register source)
{
union
{
struct
{
byte insts[4];
double* dest;
};
byte bytes[8];
} movsd =
{
// movsd [imm32], xmm1
0xF2, 0x0F, 0x11, // Opcode
0x05 + (8 * source), // ModR/M
dest // imm32
};
_stream.Write(movsd.bytes, sizeof(movsd.bytes));
}
This code works: the three opcode bytes and the ModR/M byte are written to insts
, the destination (imm32
) is written to dest
, and bytes
contains the entire instruction in raw bytes, ready to be written to the instruction stream.
However, I am curious as to whether this method of initializing the union is safe/portable. Is it OK to initialize the four values of insts
and the value of dest
within a single set of braces?
In other words, is this the correct, portable way of doing this, or should I do it a different way?
Thanks!
Upvotes: 1
Views: 713
Reputation: 66981
http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx
Anonymous Structures
A Microsoft C extension allows you to declare a structure variable within another structure without giving it a name. These nested structures are called anonymous structures. C++ does not allow anonymous structures.
You can access the members of an anonymous structure as if they were members in the containing structure.
However, you don't need a union
for what you're doing.
void WriteValueToMemory(double* dest, SSE2Register source)
{
struct
{
byte insts[4];
double* dest;
} movsd =
{ // movsd [imm32], xmm1
0xF2, 0x0F, 0x11, // Opcode
0x05 + (8 * source), // ModR/M
dest // imm32
};
_stream.Write(&movsd, sizeof(movsd));
}
Upvotes: 2