Best way in D2 to rotate a ubyte[4] array

spir denis.spir at gmail.com
Thu Mar 10 15:17:41 PST 2011


On 03/10/2011 11:01 PM, bearophile wrote:
> While creating the rotation code I have found two things I don't understand. Maybe some of you is able to help me understand.
>
> This version of the code:
>
>
> union Four {
>      uint u;
>      ubyte[4] a;
> }
> void main() {
>      Four f;
>      asm {
>          rol f.u, 8;
>      }
> }
>
>
> DMD 2.052 gives this error, do you know why?
>
> test.d(8): bad type/size of operands 'f.u'
>
> ----------------------------------
>
> So to avoid wasting load asm instructions I have tried to write it like this:
>
>
> union Four {
>      ubyte[4] arr;
>      uint ui;
> }
> void main() {
>      Four fo;
>      fo.arr[0] = 1;
>      fo.arr[1] = 2;
>      fo.arr[2] = 3;
>      fo.arr[3] = 4;
>      uint* uptr =&(fo.ui);
>      asm {
>          rol [uptr], 8;
>      }
>      asm {
>          rol uptr, 8;
>      }
> }
>
>
> but looking at the asm it produces, do you know why the rol with [uptr] and uptr are translated to the same instruction (so it rotates the pointer instead of the pointed uint)?
>
>
> __Dmain comdat
>      push EBP
>      mov EBP,ESP
>      sub ESP,8
>      mov dword ptr -8[EBP],0
>      lea EAX,-8[EBP]
>      mov byte ptr -8[EBP],1
>      mov byte ptr -7[EBP],2
>      mov byte ptr -6[EBP],3
>      mov byte ptr -5[EBP],4
>      mov -4[EBP],EAX
>      rol -4[EBP],8  ;<======
>      rol -4[EBP],8  ;<======
>      mov ESP,EBP
>      pop EBP
>      ret
>
> Bye and thank you,
> bearophile

About first point: looks like a bug at the interface between union and asm. I 
could rol either a pointer or an uint, but none of them member of a union. 
Dunno why. Indeed, using '<<' works as expected.
But I could have this work (which rather confirms the above interpretation):

union Four {
     uint u;
     ubyte[4] a;
}

void main() {
     Four f;

     f.u = 0x_01_02_03_04u;
     writefln ("'0x%08X'" , f.u);

     // deceiving D:
     auto p = &(f.u);
     auto u = *p;

     asm {
         rol u, 8;
     }
     writefln ("'0x%08X'" , u);

     /*  output:
     '0x01020304'
     '0x02030401'
     */
}

I have no idea about the second point.

Denis
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d-learn mailing list