web-dev-qa-db-ja.com

ARMのエンディアン変換

ARMでビッグエンディアンをリトルエンディアンに変換するにはどうすればよいですか?

15
seyoung

ARMのエンディアンモードについて話しているのですか、それとも他のビッグエンディアンプロセッサによって書かれたものを読んでいるのですか?

通常、ビッグ/リトルエンディアンとの間で変換する場合は、バイトを入れ替えます。したがって、0xABCDは16ビット数として表示される場合は0xCDABであり、0x12345678は32ビット数として表示される場合は0x78563412です。

ARMコアarmv5以前(ARM7、ARM9など)には、BE-32と呼ばれるエンディアンモードがあります。これは、ビッグエンディアンのWord不変を意味します。 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以降がバイト不変であるため、同じアドレスへのバイトアクセスは同じ値になり、ビッグエンディアンモードの場合、これらのアーキテクチャではハーフワード、ワード、およびダブルワードのアクセスがスワップされます。命令フェッチはスワップされず、リトルエンディアンのコンパイル済みプログラムの実行中にエンディアンビットがpsrにあるため、ビッグエンディアンに切り替えて、いくつかの命令を実行してからネイティブモードに戻ると、命令フェッチに影響を与えたり、割り込みをかけたりすることはありません。起こる。

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

一部のWebページでは、ネイティブのリトルエンディアンを実行し(非常に良いアイデア)、アセンブラーを使用してスワップを実行する場合に備えて、この4命令バイトスワップについて言及しています(常に良いアイデアとは限りません。実行内容によって異なります)。

 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 
22
old_timer

バイト反転コマンド、つまり(__REV()、__ REV16()、__ REVSH())があるかどうかを確認します。これらは、上記の回答の遅いがポータブルな回避策とは異なり、ハードウェアを利用するインラインアセンブリ命令です。 ( link1link2

5
nimig18

Cのような高級言語でエンディアンをどのように変換するかを考え、それを簡単にARM Assembly、e.g。

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

したがって、16ビットの場合、2つのシフト(1つは左と1つは右)とORがあります。あなたは3つの指示でこれを行うことができるはずです。

2
Paul R