ARM中的字节顺序转换

时间:2010-11-26 15:48:39

标签: arm endianness

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

3 个答案:

答案 0 :(得分:21)

您是在谈论ARM的endian模式,还是阅读其他大端处理器编写的内容等?

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

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

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

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

对于armv6或更新版本,如果某个地址的ldr导致0x12345678,那么在大端模式下,来自同一地址的ldr将导致0x78563412。请注意,对于armv6或更新版本上的该地址的指令获取大或小端模式将获取0x12345678。一个ldrb小端模式armv6相同的数据相同地址导致0x78,ldrb大端armv6或更新也导致0x78。这是因为armv6和更新的字节不变,意味着对同一地址的字节访问导致相同的值,在大端模式下,在这些体系结构上交换半字,字和双字访问。因为指令提取没有被交换,并且因为在运行一个小的endian编译程序时,endian位在psr中,你可以切换到big endian,执行一些指令然后返回到本机模式,它不会影响指令读取也不会中断发生。

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

答案 1 :(得分:5)

查看是否存在字节反转命令,即(__ REV(),__ REV16(),__ REVSH())。这些是使用硬件的内联汇编指令,而不像上面的答案慢速但便携的工作。 (link1link2

答案 2 :(得分:2)

考虑如何在C语言等高级语言中转换字节序,然后当您明白可以轻松地将其转换为ARM程序集时,例如

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

因此,对于16位情况,您有两个班次(一个左侧和一个右侧)和一个OR。您应该可以在3条说明中执行此操作。