Friday, 21 June 2013

Converting endianness

ARM v6 has a rev instruction to convert big- and little-endian values. A sheevaplug uses ARM v5TE so we have to do the inversion explicitly

# swaptest.s – Converting big-endian to little-endian and vice-versa
# In Arm V6 we can use the  rev instruction - but not supported on v5TE
.globl _start
.section .data
vstart:
 .word 0x12345678
.text
.align 2
_start:
 ldr r1, =vstart
 ldr r0, [r1]             @ load word to r0
 and r2, r0, #0xff000000  @ load the top 2 bytes to r2
 and r3, r0, #0x00ff0000  @ load the next 2 bytes to r3
 and r4, r0, #0x0000ff00  @ load the next 2 bytes to r4
 and r5, r0, #0x000000ff  @ load the bottom 2 bytes to r5
 mov r0, r2, lsr #24      @ shift r2 bytes to bottom and store to r0
 orr r0, r3, lsr #8       @ or the remaining shifted data
 orr r0, r4, lsl #8
 orr r0, r5, lsl #24
_stop:
 mov     r7, #1           @ set r7 to 1 - the syscall for exit
 swi     0                @ then invoke the syscall from linux


bob@poland:~/www/examples$ grep architecture /proc/cpuinfo
CPU architecture: 5TE
bob@poland:~/www/examples$
bob@poland:~/www/examples$ gdb endian
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabi".
For bug reporting instructions, please see:
...
Reading symbols from /home/bob/www/examples/endian...done.
(gdb) b _start
Breakpoint 1 at 0x8078: file endian.s, line 10.
(gdb) b _stop
Breakpoint 2 at 0x80a0: file endian.s, line 21.
(gdb) run
Starting program: /home/bob/www/examples/endian 

Breakpoint 1, _start () at endian.s:11
11  ldr r0, [r1]  @ load word to r0
Current language:  auto
The current source language is "auto; currently asm".
(gdb) x/x &vstart
0x100a8 : 0x12345678
(gdb) cont
Continuing.

Breakpoint 2, _stop () at endian.s:22
22  swi     0   @ then invoke the syscall from linux
(gdb) p/x $r0
$2 = 0x78563412
(gdb) quit
A debugging session is active.

 Inferior 1 [process 17053] will be killed.

Quit anyway? (y or n) y
bob@poland:~/www/examples$

So we see the inverted data in r0 when the program stops.

No comments:

Post a Comment