web-dev-qa-db-ja.com

非常に単純なARM命令をバイナリ/ 16進数に変換する

私はこのページと、非常にシンプルな表現方法を理解するためのさまざまなガイド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進/マシンコードに変換する方法を実際に確認できるものはありません。組み立てました。

よろしくお願いします。

24
n00neimp0rtant

データ処理命令のコーディング方法は次のとおりです。

ARM data processing instructions

自分のページに条件コード表があります。レジスタは0000 使って 1111

すべての例は同じカテゴリに分類されます。写真は、HDD上のドキュメントから抽出されていますが、 google で見つけることもできました。これらの指示をコーディングするのは退屈な仕事です。

そう、 mov r0, r0は次のようになります。

1110 00 0 0 1101 0000 0000 00000000

MOVには実際には適用されないため、Rn= 0にします。CMPの場合、Sは常に1です。

32
Roman Saveljev

まず、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になります。

10
old_timer

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になります。

6
Nico Erfurth