Endianness conversion in ARM

随声附和 提交于 2020-01-09 10:04:28

问题


How do I convert big endian to little endian in ARM?


回答1:


Are you talking about ARM's endian modes, or reading something written by some other big endian processor, etc?

Normally converting to/from big/little endian you swap the bytes around. So 0xABCD is 0xCDAB when viewed as a 16 bit number 0x12345678 is 0x78563412 when viewed as a 32 bit number.

ARM cores armv5 and older (ARM7, ARM9, etc) have an endian mode known as BE-32, meaning big endian word invariant. armv6 and newer (mpcore, cortex-somethings) have BE-8, or big endian byte invariant.

So if you are using an armv4 for example in big endian mode and native (little) endian mode a word read (ldr) of the value 0x12345678 would be 0x12345678 for a big endian word read at the same address. Word invariant meaning word reads give the same answer. A byte read of address zero in little endian mode of the same address would be 0x78 and big endian byte read (ldrb) would be 0x12.

So you have to go beyond just saying is it big or little endian but what instruction is being used.

For an armv6 or newer, if an ldr at some address results in 0x12345678 then in big endian mode the ldr from the same address would result in 0x78563412. Note that big or little endian mode an instruction fetch for that address on an armv6 or newer would fetch 0x12345678. An ldrb little endian mode armv6 same data same address results in 0x78, ldrb big endian armv6 or newer also results in 0x78. this is because the armv6 and newer are byte invariant meaning byte accesses to the same address result in the same value, halfword, word and double word accesses are swapped on these architectures when in big endian mode. Because instruction fetches are not swapped, and because the endian bit is in the psr while running a little endian compiled program you can switch to big endian, do a number of instructions then return to native mode and it wont affect the instruction fetches nor interrupts that occur.

setend be
ldr r0,[r1]
add r0,r0,#7
str r0,[r1]
setend le

Some web pages will mention this four instruction byte swap, in case you want to run native little endian (a very good idea) and perform the swap using assembler (not always a good idea, depends on what you are doing).

  eor r3,r1,r1, ror #16
  bic r3,r3,#0x00FF0000
  mov r0,r1,ror #8
  eor r0,r0,r3, lsr #8

with r1 being the input it appears and r0 being the output

For armv6 or newer the above can be performed with

  rev r0,r1



回答2:


See if there is a byte reversal command i.e. (__REV(), __REV16(), __REVSH()). These are inline assembly instructions that utilizes the hardware unlike the slower but portable work around answers above. (link1, link2)




回答3:


Think about how you would convert endianness in a high level language like C, and then when you understand that you can easily translate it into ARM assembly, e.g.

uint16_t x = 0x0102;
uint16_t y = (x << 8) | (x >> 8); // y = 0x0201

So for the 16 bit case you have two shifts (one left and one right) and an OR. You should be able to do this in 3 instructions.



来源:https://stackoverflow.com/questions/4286671/endianness-conversion-in-arm

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!