Inline Assembly
One of the really neat features of D is the ability to put assembly language directly inline with the rest of your code. For systems programmers, this could potentially save them a bit of time when optimizing their code. Below is a commented example of how inline assembly works in D:
// I based this sample off of a test case walter bright wrote. I added the
// XOR operation and comments.
import std.stdio;
import std.string;
// use the version command to see if this is an x86 or x86/64 architecture
version(D_InlineAsm_X86)
{
version = runInineX86AssemblyTest;
}
else version(D_InlineAsm_X86_64)
{
version = runInineX86AssemblyTest;
}
else
{
static assert(0, "DSTRESS{XFAIL}: no inline x86 Assembly support");
}
// If x86 is the architecture, run the code in this block
version(runInineX86AssemblyTest)
{
ubyte b = 0xAA;
int main()
{
void* x = &b; // This is a pointer to b (an unsigned byte with the value 10101010)
void* y; // This is a null void pointer
writeln("Addresses Before: x=" ~ toString(cast(long)x) ~ ", y=" ~ toString(cast(long)y));
writeln("Values Before: *x=" ~ toString(*cast(ubyte*)x) ~ ", *y=(null pointer exception)");
writeln(`
Using Assembly Language, XOR variable b (170) and value 0xFF (255).
10101010 xor 11111111 = 01010101 = 64 + 16 + 4 + 1 = 85
Then copy the address of b to the void pointer y.
`);
static if(size_t.sizeof == 4) // 4 byte pointer (32 bit OS)
{
asm
{
mov EAX, offsetof b; // Move the address of b to the EAX register
xor [EAX], 255; // Reverse the bits by doing an XOR on 0xFF.
mov y, EAX; // Copy the address in EAX to y
}
}
else static if(size_t.sizeof == 8) // 8 byte pointer (64 bit OS)
{
asm
{
mov RAX, offsetof b; // Move the address of b to the RAX register
xor [RAX], 255; // Reverse the bits by doing an XOR on 0xFF.
mov y, RAX; // Copy the address in RAX to y
}
}
else
{
pragma(msg, "DSTRESS{ERROR}: unsupported pointer size");
static assert(0);
}
if(x != y)
{
assert(0);
}
writeln("Addresses After: x=" ~ toString(cast(long)x) ~ ", y=" ~ toString(cast(long)y));
writeln("Values After: *x=" ~ toString(*cast(ubyte*)x) ~ ", *y=" ~ toString(*cast(ubyte*)y));
getc(stdin);
return 0;
}
}
And here is the programs output:
Addresses Before: x=4296832, y=0
Values Before: *x=170, *y=(null pointer exception)
Using Assembly Language, XOR variable b (170) and value 0xFF (255).
10101010 xor 11111111 = 01010101 = 64 + 16 + 4 + 1 = 85
Then copy the address of b to the void pointer y.
Addresses After: x=4296832, y=4296832
Values After: *x=85, *y=85





