ARM中的字节顺序转换

sey*_*ung 15 arm endianness

如何在ARM中将big endian转换为little endian?

old*_*mer 22

你是在谈论ARM的endian模式,还是读一些其他大端处理器等写的东西?

通常转换为/从big/little endian转换你周围的字节.因此,当被视为32位数时,0xABCD为0xCDAB,当被视为32位数时,0x12345678为0x78563412.

ARM内核armv5及更早版本(ARM7,ARM9等)的端序模式称为BE-32,意味着大端字不变.armv6和更新(mpcore,cortex-somethings)有BE-8或大端字节不变量.

因此,如果您在大端模式和本机(小)端模式下使用armv4,则对于在同一地址读取的大端字,值0x12345678的字读取(ldr)将为0x12345678.单词不变意义词读取给出相同的答案.在相同地址的小端模式中,地址0的字节读取将是0x78,而大端字节读取(ldrb)将是0x12.

所以你必须超越只是说它是大或小端,但正在使用什么指令.

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

有些网页会提到这四个指令字节交换,如果你想运行本机小端(一个非常好的主意)并使用汇编程序执行交换(并不总是一个好主意,取决于你在做什么).

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

r1是输入,r0是输出

对于armv6或更新版本,可以执行上述操作

  rev r0,r1


nim*_*g18 5

查看是否有字节反转命令,即(__REV(),__ REV16(),__ REVSH())。这些是内联汇编指令,利用了硬件,而不像上面的答案那样较慢但可移植。(link1link2


Pau*_*l R 3

考虑一下如何在 C 等高级语言中转换字节序,然后当您理解后,您可以轻松地将其转换为 ARM 汇编,例如

uint16_t x = 0x0102;
uint16_t y = (x << 8) | (x >> 8); // y = 0x0201
Run Code Online (Sandbox Code Playgroud)

因此,对于 16 位情况,您有两个移位(左移和右移)和一个 OR。您应该能够通过 3 条指令来完成此操作。