私はこのページと、非常にシンプルな表現方法を理解するためのさまざまなガイドARMバイナリおよび16進数としての命令。それは私にとって簡単なプロセスであるように思えますが、私はまだ理解していません。以下に例を示します。
基本的なNOP:
what goes here? what goes here?
_↓_ _____↓____
| | | |
mov r0, r0 ; ????00?1101?????????????????????
|__||__|
↑ ↑
how do I express registers?
他の人にも同じ基本的な質問。
2つのレジスタの比較:
cmp r1, r0
レジスタ値への即時の追加:
add r0, #0x1a
これらのオンラインチュートリアルはすべて、これらのような命令の使用方法を説明するのに優れていますが、ARM命令を取得先のバイナリ/ 16進/マシンコードに変換する方法を実際に確認できるものはありません。組み立てました。
よろしくお願いします。
データ処理命令のコーディング方法は次のとおりです。
自分のページに条件コード表があります。レジスタは0000
使って 1111
。
すべての例は同じカテゴリに分類されます。写真は、HDD上のドキュメントから抽出されていますが、 google で見つけることもできました。これらの指示をコーディングするのは退屈な仕事です。
そう、 mov r0, r0
は次のようになります。
1110 00 0 0 1101 0000 0000 00000000
MOV
には実際には適用されないため、Rn= 0にします。CMP
の場合、S
は常に1です。
まず、infocenter.arm.comのARM Architectural Reference Manual(ARM ARM)、リファレンスマニュアルが必要です。最も古いもの(armv5など)を取得します。命令セットは、そこ。
第二に、なぜいくつかの指示を組み立てて何が起こるのか見てみませんか?
;@test.s
cmp r1, r0
add r0, #0x1a
あなたが持っているクロスアセンブラが何であれ(スクリプトのビルドgccディレクトリの http://github.com/dwelch67/raspberrypi を参照してください、そのスクリプトのbinutilsを介して実行してください)
arm-none-linux-gnueabi-as test.s -o test.o
arm-none-linux-gnueabi-objdump -D test.o
arm-none-linux-gnueabi対arm-none-elf対arm-elfなど、このことは関係ありません。すべて同じです
Disassembly of section .text:
00000000 <.text>:
0: e1510000 cmp r1, r0
4: e280001a add r0, r0, #26
完全な32ビットアーム命令(サムではない)の上位4ビットは条件コードです。ARMARM。0xEは常にこの命令を実行することを意味します。0b0000の条件フィールドセクションを参照してください。 eqはzフラグが設定されている場合のみ実行され、0b0001 neはzがクリアされている場合のみ実行されます。
ARM ARM arm命令セットにプッシュしてから、arm命令のアルファベット順のリストに移動し、cmpを見つけます。cond00I10101 rn sbz shifterで始まります。
上記のcmp命令から、1110 000101010001が表示されます...だから、私はゼロビットです15:12はゼロビット27:26はゼロであり、24:21は1010ですので、これはcmp命令です
上記のビット19から16は0b001であり、rnであるため、ARM ARMのアドレス指定を確認するように指示します。モード1データ処理のオペランドであり、pdfにページへのリンクがあります
第2オペランドを単にデータ処理オペランドと呼ばれるレジスタにすることを知っています-レジスタ、およびページ番号、そのページのそのページに移動します15:12はrd 11:4はゼロで、3:0はrmです。 cmp命令から、15:12は0でなければならないことがわかります。気にするかどうか、cmpは結果をレジスタに保存しないので、rdは使用されません。 rmが使用されます。この場合、r0が必要です。したがって、0b0000は3:0になります。また、ビット27:25がゼロであることに注意してください。cmp命令25ではIです。
cmpページとこのデータ処理の間-登録ページには全体像があります
1110 condition
000
1010 opcode
1 S (store flags, that is a 1 for a cmp to be useful)
0001 rn
0000 rd/dont care/sbz
00000
000
0000 rm
cmp rn,rm
cmp r1,r0
追加も同様ですが、即時を使用するため、命令のアルファリストの追加命令に進みます。 cmpから、このクラスの命令の24:21がオペコードであることがわかりました。シフターオペランドにまっすぐ進んでそこから続行できます。
今回はrd、rn、#immediateを追加しています
#immediateのページを探してください
エンコーディングは
1110 condition, always
001 (note the immediate bit is set)
0100 (opcode for add for this type of instruction)
0 (S not saving the flags, it would be adds r0,r0,#26 for that)
0000 (rn = r0)
0000 (rd = r0)
ここからが興味深い部分です。26種類の方法をエンコードできます。ビット7:0はイミディエイトで、ビット11:8はイミディエイトを回転できます。26は0x1Aです。下位8ビットに0x1Aを入れて回転を0に設定するだけで、それがgnuアセンブラーで行われました。おそらく、下位8ビットに0x68を配置し、rotate_immフィールドに1を右に1100回転した1101000を配置すると、11010 = 0x1A = 26になります。
ARM ARM=のコピーを取得する必要があります。これは、すべての命令のエンコードを説明しています。
ほとんどのARM命令は、条件付きコードに上位4ビットを使用します。条件付きで命令を実行したくない場合は、疑似条件AL(1110)を使用します。
エンコードの最初のレジスタ(Rn)はMOV命令には使用されず、ARM ARMによって定義されるように0000に設定する必要があります。
2番目のレジスタはデスティネーションです。ここではレジスタ番号をエンコードするだけであるため、r0をデスティネーションとして使用しているため、0000にもなります。r4の場合は0100になります。
残りは、非常に柔軟な、いわゆるシフターオペランドです。あなたの場合のような単純なレジスタ(r0)である場合、最後の4ビットが再びレジスタをエンコードするのはちょうど0000 0000 0000です。また、さまざまなタイプのシフトをエンコードし、データ処理のレジスタ値または即値でローテーションします。
ただし、最下位ビットに8ビットがエンコードされ、最初の4ビットが2ビットステップで右ローテートを定義する場合もあります。この場合、bit25も1になり、その他の場合はすべて0になります。