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