Go4Expert

Go4Expert (http://www.go4expert.com/)
-   Assembly Language Programming (ALP) Forum (http://www.go4expert.com/forums/assembly-language-programming-forum/)
-   -   Swaping in Assembly (http://www.go4expert.com/forums/swaping-in-assembly-t18287/)

dsptl 2Jul2009 03:07

Swaping in Assembly
 
How can you exchange(swap) the first bit and the last bit of register %o0 in Assembly?

xpi0t0s 2Jul2009 16:15

Re: Swaping in Assembly
 
Here's a quick test program I wrote in C; compile to assembler to get the result for your specific hardware:
Code:

void swapbits()
{
        for (int i=0; i<4; i++)
        {
                int reg=0, exp=0, reg1;

                switch (i)
                {
                case 0: reg=0xffff0000; exp=0x7fff0001; break; // 1xx0 -> 0xx1
                case 1: reg=0xffff0001; exp=0xffff0001; break; // 1xx1 -> 1xx1
                case 2: reg=0x7fff0001; exp=0xffff0000; break; // 0xx1 -> 1xx0
                case 3: reg=0x7fff0000; exp=0x7fff0000; break; // 0xx0 -> 0xx0
                }
                reg1=reg;
                if (reg>0 && reg&1 || reg<0 && !(reg&1))
                        reg ^= 0x80000001;
                printf("Swap 0x%04x, expect 0x%04x, result 0x%04x, %s\n", reg1, exp, reg,
                        (exp==reg) ? "OK" : "NOK");               
        }
}

Most of it is just a testbed for the calculation itself, which is just:
Code:

                if (reg>0 && reg&1 || reg<0 && !(reg&1))
                        reg ^= 0x80000001;


xpi0t0s 3Jul2009 17:25

Re: Swaping in Assembly
 
Here's another expression that doesn't use "if" statements and should execute in constant time regardless of the bit values, unlike the previous one. Execution in constant time is useful for programming embedded systems. With disassembly, as generated by Visual Studio 2008:
Code:

                reg ^= (- ( (reg&0x00000001) ^ ((reg&0x80000000)>>31) )) & 0x80000001;
00413B6B  mov        eax,dword ptr [reg]
00413B6E  and        eax,1
00413B71  mov        ecx,dword ptr [reg]
00413B74  and        ecx,80000000h
00413B7A  shr        ecx,1Fh
00413B7D  xor        eax,ecx
00413B7F  neg        eax 
00413B81  and        eax,80000001h
00413B86  xor        eax,dword ptr [reg]
00413B89  mov        dword ptr [reg],eax

And here's a hand coded one in 9 pseudocode instructions that uses one register for the two bits, and assumes that <<= shifts the carry flag C into bit 0 and bit 31 into C, and >>= works the same way, AND not only doesn't require C to be set to anything specific but preserves its value (u) throughout:

Code:

            reg1  reg2  C
reg2=reg1;  axxb  axxb    ; goal: reg1=bxxa
reg1&=0110; 0xx0        u
reg1>>=1;  u0xx        0
reg2<<=1;        xxb0  a
reg1<<=1;  0xxa        u
reg1<<=1;  xxau        0
reg2>>=1;        0xxb  0
reg2>>=1;        00xx  b
reg1>>=1;  bxxa        u

This can be reduced to 7 instructions if two consecutive <<=1's and >>=1's have exactly the same effect as a single <<=2 or >>=2. Note <<= and >>= are NOT equivalent to the C instructions because these shift a zero bit into the register and lose the bit that drops off the end.

xpi0t0s 3Jul2009 21:01

Re: Swaping in Assembly
 
And here's one in just six (realised the &=0110 wasn't necessary):
Code:

reg2=reg1  axxb  axxb  u
reg1<<=1    xxbu        a
reg2>>=1          aaxx  b
reg1>>=2    ubxx        b
reg2<<=1          axxb  a
reg1<<=1    bxxa        u



All times are GMT +5.5. The time now is 19:16.