asm woes...
Era Scarecrow via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri May 27 01:20:02 PDT 2016
Well decided I should dig my hand in assembly just to see if it
would work. Using wideint.d as a starting point I thought I would
do the simplest operation I could do, an increment.
https://github.com/d-gamedev-team/gfm/blob/master/integers/gfm/integers/wideint.d
https://dlang.org/spec/iasm.html
Most of my code was failing outright until I looked at the
integrated assembler page, which TDPL doesn't go into at all. To
access variables for example I have to do var[ESP] or var[RSP] to
access it from the stack frame. Unintuitive, but sure I can work
with it.
So the code for incrementing is pretty simple...
@nogc void increment() pure nothrow
++lo;
if (lo == 0) ++hi;
}
That's pretty simple to work with. I know the assembly
instructions can be done 1 of 2 ways.
add lo, 1
adc hi, 0
OR
inc lo
jnc L1 //jump if not carry
inc hi
So I've tried. Considering the wideint basically is self calling
if you want to make a larger type than 128bit, then that means I
need to leave the original code alone if it's a type that's too
large, but only inject assembly if it's the right time and size.
Thankfully bits is there to tell us.
So, add version
@nogc void increment() pure nothrow
{
static if (bits > 128) {
++lo;
if (lo == 0) ++hi;
} else {
version(X86) {
asm pure @nogc nothrow {
add lo[ESP], 1;
adc hi[ESP], 0;
}
} else {
++lo;
if (lo == 0) ++hi;
}
}
}
I compile and get: Error: asm statements cannot be interpreted
at compile time
The whole thing now fails, rather than compiling to do the
unittests... Doing the inc version gives the same error..
asm pure @nogc nothrow {
inc lo[ESP];
jnc L1;
inc hi[ESP];
L1:;
}
Naturally it wasn't very specific about if I should rely on RSP
or ESP or what, but since it's X86 rather than X86_64 I guess
that answers it... would be easy to write the x64 version, if it
would let me.
So i figure i put a check for __ctfe and that will avoid the
assembly calls if that's the case. So...
version(X86) {
@nogc void increment() pure nothrow
{
if (!__ctfe && bits == 128) {
asm pure @nogc nothrow {
add lo[ESP], 1;
adc hi[ESP], 0;
}
} else {
++lo;
if (lo == 0) ++hi;
}
}
} else {
//original declaration
}
Now it compiles, however it hangs the program when doing the
unittest. Why does it hang the program? I have no clue. Tried
changing the ESP to EBP just in case that was actually what it
wanted, but doesn't seem to be the case. I can tell how I will be
refactoring the code, assuming i can figure out what's wrong in
the first place...
Anyone with inline assembly experience who can help me out a
little? 2 add instructions shouldn't cause it to hang...
More information about the Digitalmars-d-learn
mailing list