4

Assume we save the number 1 in the EAX-Register and we swap the most significant byte with the least significant byte. Is the new swapped number 256 or 16777216?

I tried it in a assembler program by swapping the value of the AL- with the value of the AH-Register. My result was 256. I do not think that this is correct and neither I understand the result of 256. I tought the EAX-Register is 32 Bit, not 16 Bit.

The Question is related to the correct result of the swap.

Razmo
  • 81
  • 2
  • 6
  • Possible duplicate of [Assembly programming memory Allocating EAX vs Ax, AH, AL](https://stackoverflow.com/questions/15191178/assembly-programming-memory-allocating-eax-vs-ax-ah-al) – J... Aug 11 '17 at 17:04
  • EAX is 32 bit, AX is the lower 16 bits of EAX, AL and AH are the low and high bytes of AX. There is no direct access to the top 16 bits of EAX. See, related : [Get the upper half of the EAX register](https://stackoverflow.com/q/15230268/327083) – J... Aug 11 '17 at 17:05
  • How can i get the upper bits of the EAX Register, if I can get the lower 16 with the AX Register? – Razmo Aug 11 '17 at 17:07
  • See above...... – J... Aug 11 '17 at 17:07
  • The value of `0x00000001` when swapping the least and most significant bytes is `0x01000000`, naturally. If you're asking what the decimal representation of that value is when interpreting it as an integer then, yes, the value is 16777216. – J... Aug 11 '17 at 17:16
  • AH is the 2nd byte of EAX. It's the top byte of AX, not EAX or RAX. – Peter Cordes Aug 13 '17 at 01:36

1 Answers1

7

There is a special opcode for this, called BSWAP, for example:

    MOV     EAX,1   ; EAX is 0x00000001  or 1 decimal  
    BSWAP   EAX     ; EAX is 0x01000000  or 16777216 decimal

It will swap all 4 bytes of any 32 bit general purpose register. This converts little-endian 32 bit values to big-endian and vice versa.

FWIW, to swap the bytes of a 16 bit value, e.g. in AX, you can do

    MOV     AX,1    ; AX is 0x0001 or 1 decimal
    XCHG    AL,AH   ; AX is 0x0100 or 256 decimal

Or, according to @PeterCordes:

    MOV     AX,0x1234
    ROL     AX,8    ; AX is 0x3412 now

There is no special opcode to swap only the top and low bytes of a 32 bit register (and leave the other two intact). You can only do something like this:

Edit

<removed code using ROR, XCHG AL,AH, ROL and BSWAP>

As @Fifoernik pointed out in a comment (thanks!), much easier than the code I removed is the following:

    MOV     EAX,0x12345678
    ROL     EAX,8   ; EAX is 0x34567812  rotate left one byte: 12 34 56 78 --> 34 56 78 12
    XCHG    AL,AH   ; EAX is 0x34561278  swap 12 and 78:       34 56 78 12 --> 34 56 12 78
    ROR     EAX,8   ; EAX is 0x78345612  rotate back:          34 56 12 78 --> 78 34 56 12

Edit 2

As @PeterCordes points out, this might even be a little faster:

    MOV     EAX,0x12345678
    ROL     EAX,8   ; EAX is 0x34567812  rotate left one byte: 12 34 56 78 --> 34 56 78 12
    ROL     AX,8    ; EAX is 0x34561278  swaps 12 and 78:      34 56 78 12 --> 34 56 12 78
    ROR     EAX,8   ; EAX is 0x78345612  rotate back:          34 56 12 78 --> 78 34 56 12

But I didn't time either of those.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • Perhaps it would be useful to illustrate to OP why exchanging ah and al yielded this result. – fuz Aug 11 '17 at 22:02
  • Why insisting on using `BSWAP` in the last snippet? It only requires these 3 steps: `ROL EAX,8` `XCHG AL,AH` ` ROR EAX,8`. – Fifoernik Aug 12 '17 at 13:36
  • `ROL AX,8` should be more efficient than `xchg al,ah` on most CPUs, since it's 1 uop instead of 3. It also avoids any partial-register merging uops on Intel Haswell/Skylake. It also works on any reg, including R8W...R15W. (high8 registers are slower than low8/low16 registers for some purposes on Intel Haswell/Skylake; in the middle of writing up a Q&A about this; will post a link when done. summary: I think only AH gets renamed separately from RAX; AL and AX don't. Also, reading AH adds an extra 1c of latency.) – Peter Cordes Aug 13 '17 at 01:35
  • 1
    This is cool. I first had a 2 register solution, then a 1 register solution, then that was refined by Fifoernik to rotate the other way around, and now even AX is rotated by Peter Cordes. Although, for someone not familiar with x86 assembly, `XCHG AL,AH` may be easier to understand than `ROL AX,8`, even if both achieve the same. – Rudy Velthuis Aug 13 '17 at 08:27