2

So I figured out how to reverse the endianess of a four byte long int in C:

unsigned int swapWord (unsigned int n){
   return (n>>24) | ((n<<8) & 0x00FF0000) |((n>>8) & 0x0000FF00) | (n<<24);
}

Now I know I can just disassemble this, and I did, and it was decent code, but I'm sure there is a more efficient way to reverse the endianess. Any ideas?

Edit: Here's the disassembled code:

00000000004005a3 <swapWord>:
      4005a3:   55                      push   %rbp
      4005a4:   48 89 e5                mov    %rsp,%rbp
      4005a7:   89 7d fc                mov    %edi,-0x4(%rbp)
      4005aa:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005ad:   c1 e8 18                shr    $0x18,%eax
      4005b0:   89 c2                   mov    %eax,%edx
      4005b2:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005b5:   c1 e0 08                shl    $0x8,%eax
      4005b8:   25 00 00 ff 00          and    $0xff0000,%eax
      4005bd:   09 c2                   or     %eax,%edx
      4005bf:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005c2:   c1 e8 08                shr    $0x8,%eax
      4005c5:   25 00 ff 00 00          and    $0xff00,%eax
      4005ca:   09 c2                   or     %eax,%edx
      4005cc:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005cf:   c1 e0 18                shl    $0x18,%eax
      4005d2:   09 d0                   or     %edx,%eax
      4005d4:   5d                      pop    %rbp
      4005d5:   c3                      retq   
      4005d6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
      4005dd:   00 00 00 
tannerwj
  • 154
  • 3
  • 11
  • What was the disassembled code; and was it a single `bswap` instruction? – Brendan Feb 08 '14 at 06:32
  • There's the disassembled code. Nah, it's a little more intense than a bswap instruction. I messed around with bswap for a bit, but don't quite understand it I guess. – tannerwj Feb 08 '14 at 08:14
  • Did you specify any optimzations when compiling? This is rather trivial optimizations and gcc emits bswap at O2 or above – phuclv Feb 08 '14 at 12:38
  • That disassembly looks like a literal translation of the C code to me (no optimisation enabled at all) – Brendan Feb 08 '14 at 12:56
  • Yeah I used O0, which I believe is none – tannerwj Feb 09 '14 at 19:56
  • enable optimizations and see the difference. Also, if you want Intel syntax then use [`-masm=intel`](http://stackoverflow.com/questions/199966/how-do-you-use-gcc-to-generate-assembly-code-in-intel-syntax) – phuclv Mar 06 '14 at 01:12
  • 1
    @tannerwj A literal translation of C code would not help in cases like this. You actually want O2 in this case. O2 produces `bswap eax` – quartzsaber Jul 20 '20 at 02:57

1 Answers1

5

For 80486 and later, there's an instruction called bswap that swaps bytes in a dword.

For older 80386 CPUs I'd be tempted to use something like this:

                     ;eax = 0xAABBCCDD
    xchg ah,al       ;eax = 0xAABBDDCC
    rol eax,16       ;eax = 0xDDCCAABB
    xchg ah,al       ;eax = 0xDDCCBBAA

For even older CPUs (8086 to 80286) you have to use a pair of 16-bit registers (as there are no 32-bit registers), and it ends up like this:

                     ;dx:ax = 0xAABBCCDD
                     ;ax:dx = 0xCCDDAABB
    xchg ah,al       ;ax:dx = 0xDDCCAABB
    xchg dh,dl       ;ax:dx = 0xDDCCBBAA

Note: Instead of using xchg ah,al you could use either ror ax,8 or rol ax,8. I doubt it makes much difference which of these 3 instructions you use.

Brendan
  • 35,656
  • 2
  • 39
  • 66
  • That looks pretty efficient. But I'm new to assembly, what's the difference between the type of assembly you have and the kind I have? – tannerwj Feb 08 '14 at 08:16
  • The difference is, that this one is Intel syntax and your dissassembly is AT&T syntax. The code is the same though. – Devolus Feb 08 '14 at 09:18