ARM中的字节序转换 [英] Endianness conversion in ARM

查看:65
本文介绍了ARM中的字节序转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 ARM 中将大端转换为小端?

解决方案

你是在谈论 ARM 的字节序模式,还是在阅读其他一些大字节序处理器编写的内容等?

通常在大端/小端之间进行转换,您可以交换字节.所以 0xABCD 被视为 16 位数字时是 0xCDAB 0x12345678 是 0x78563412 时被视为 32 位数字.

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

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

所以你必须不仅仅是说它是大端还是小端,而是使用什么指令.

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

<前>设定为ldr r0,[r1]添加 r0,r0,#7str r0,[r1]设置乐

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

<前>或 r3,r1,r1, ror #16bic r3,r3,#0x00FF0000mov r0,r1,ror #8或 r0,r0,r3, lsr #8

r1 是它出现的输入,r0 是输出

对于 armv6 或更新的版本,可以使用

<前>转速 r0,r1

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

解决方案

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

这篇关于ARM中的字节序转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆