stm32mp157 Linux 開発ボードに基づく ARM ベアメタル開発チュートリアル 5: ARM マイクロプロセッサ命令システム (シリアル)

序文:

現在、ARM Cortex-A7 ベアメタル開発ドキュメントとビデオは 2 回アップグレードされ、内容がより充実し、説明がより詳細になるように継続的に更新されています。全文で使用されている開発プラットフォームは Huaqing Yuanjian FS-MP1A 開発ボードです(STM32MP157開発ボード)

FS-MP1A 開発ボードには、Cortex-A7 ベアメタル開発に加えて、Cortex-M4 開発、FreeRTOS、Linux 基本およびアプリケーション開発、Linux システム移植、Linux ドライバー開発、ハードウェア設計などの他の一連のチュートリアルも含まれています。 、人工知能マシンビジョン、Qtアプリケーションプログラミング、Qt総合プロジェクト実戦など。さらに、Linux システム移植の章と Linux ドライバー開発の章のドキュメントとビデオもアップグレードされる予定ですので、ご期待ください。

開発ボードに関する詳細情報は、コメント領域の下にメッセージを残すことで入手できます~~~

ARM マイクロプロセッサ命令システム

ARM 命令セットは、ジャンプ命令、データ処理命令、プログラム ステータス レジスタ転送命令、ロード/ストア命令、コプロセッシングに分類できます。

プロセッサ命令と例外生成命令。使用する命令の種類に応じて、命令のアドレッシングモードはデータ処理命令のアドレッシングモードとメモリアクセス命令のアドレッシングモードに分けられます。

この章では主に ARM アセンブリ言語について紹介します。主な内容は以下の通りです。

⚫ ARM プロセッサのアドレッシング モード。

⚫ ARMプロセッサの命令セット

ARM 命令の構成

<オペコード> {<c>} {S} <Rd>,<Rn>,<shifter_operand>

命令分析:

<opcode>: 実行するコマンド

{<c>}: コマンド実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

表44.7.2.1 命令の実行条件

{S}: 命令の動作が CPSR に影響するかどうかを判断します。例外復帰時、演算対象が PC レジスタの場合、S フラグは

SPSR レジスタを CPSR に復元します。

<Rd>: 宛先レジスタです。

<Rn>: オペランドが配置されているレジスタ。

<shifter_operand> には、表に示すように 11 の形式があります。

MOV 命令の例をいくつか示します。

コード例 45-1 の例

1 MOV R0,#2

2 加算 R0、R0、R1

3 ムーブ R2、R0

4 MOV R1、R0、LSL #2

ARM プロセッサアドレッシングモード

ARM 命令のアドレッシングモードは、データ処理命令アドレッシングモードとメモリアクセス命令アドレッシングモードに分かれます。

データ処理命令アドレッシングモード

データ処理命令のアドレッシングモードは以下の種類に分類できます。

⚫ 即時アドレス指定モード。

⚫ レジスタアドレッシングモード。

⚫ レジスタシフトアドレッシングモード。

1.即時アドレッシングモード

命令内の即値は、8 ビット定数を偶数 4 ビット (0、2、4、...、26、28、30) シフトすることによって取得されます。したがって、各命令には 8 ビットの定数 X とシフト値 Y が含まれており、図に示すように、得られる即値 = X は右回転 (2×Y) されます。

なぜ上記の操作で即時番号を取得する必要があるのでしょうか? ここでは、ldr 命令のマシンコードを例として、その理由を分析します。

上図のimm12は即値が占有するビットフィールドですが、imm12の領域は12bitしかなく、12bitが必要であることがわかります。

このエンコーディングで任意の 32 ビット数値を表現することは絶対に不可能です。ただし、実際の開発プロセスでは、32 ビットを表すために 12 ビット エンコーディングが使用されます。

番号。次に、表現の数のみを制限し、コーディングを通じて 12 ビット コードを使用して 32 ビット数値を表現します。

上では、即値 = X 巡回右シフト (2×Y) と述べましたが、表現の範囲は広くなりますが、12 ビットで表現できる数は確実であるため、ARM ではすべての数値を表現できるわけではないと規定しています。 32 ビット定数はすべて正当な即値数であり、上記の構築方法で得られたものだけが正当な即値数です。

ARM アセンブラは、次の規則に従って即値のエンコーディングを生成します。

イミディエイト値が0~0xFFの範囲の場合、X=イミディエイト、Y=0と設定します。

他の場合には、アセンブラは Y の値を最小化するエンコーディングを選択します。

次に、即値のエンコーディングを生成するには、次のようにします。

有効な即時値の一部を以下に示します。

0xFF:X=0xFF,Y=0

0x104:X=0x41,Y=15

0xFF0:X=0xFF,Y=14

0xF000000F:X=0xFF,Y=2

下面是一些无效的立即数:

0x101、0x102、0xFF1、0xFF04、0xFF003、0xFFFFFFFF、0xF000001F

下面是一些应用立即数的指令

示例代码 45-2 立即数

1 MOV R0,#0 ;送0到R0

2 ADD R3,R3,#1 ;R3的值加1

3 CMP R7,#1000 ;将R7的值和1000比较

4 BIC R9,R8,#0xFF00 ;将 R8 中 8~15 位清零,结果保存在 R9 中

2、 寄存器寻址方式

寄存器的值可以被直接用于数据操作指令,这种寻址方式是各类处理器经常采用的一种方式,也是一种执行效率较高的寻址方式,如:

示例代码 45-3 寄存器寻址

1 MOV R2,R0 ;R0的值送R2

2 ADD R4,R3,R2 ;R2加R3,结果送R4

3 CMP R7,R8 ;比较 R7 和 R8 的值

3、 寄存器移位寻址方式

和寄存器寻址类似,只是操作前需要对寄存器操作数进行移位操作。寄存器的值在被送到 ALU 之前,可以事先经过桶形移位寄存器的处理。预处理和移位发生在同一周期内,所以有效地使用移位寄存器,可以增加代码的执行效率。

LSL<c> <Rd>, <Rm>, #<imm5>

LSR<c> <Rd>, <Rm>, #<imm>

ASR<c> <Rd>, <Rm>, #<imm>

ROR{S}<c> <Rd>, <Rm>, #<imm>

RRX{S}<c> <Rd>, <Rm>

{<c>}: 为指令执行的条件码。当忽略< c >时,指令为无条件执行。

<Rd>: 为目标寄存器。

<Rm>: オペランドが配置されているレジスタ。

<imm>: シフト量、範囲は 1 ~ 32。

拡張付き右回転 (RRX): オペランドは 1 ビット右にシフトされ、シフトによって空いた上位ビットには C フラグの値が埋められます。

命令で使用されるシフト演算の例をいくつか示します。

コード例 45-4 レジスタ シフト アドレッシング

1 ADD R2, R0, R1, LSR #5 ; R1 の値を論理的に 5 ビット右にシフトし、結果を R0 と R2 に加算します。

2 MOV R1, R0, LSL #2 ; R0 の値を論理的に 2 ビット左にシフトし、結果を R1 に転送します

3 SUB R1, R2, R0, LSR #4 ; R2 の値から R0 の値を減算し、R0 の値を右に 4 ビットシフトし、結果を R1 に転送します

4 MOV R2, R4, ROR R0 ; R4の値を右にR0回移動し、その結果をR2に転送します

メモリアクセス命令アドレッシングモード

メモリアクセス命令のアドレッシングモードは以下の種類に分類できます。

⚫ ワードおよび符号なしバイトのロード/ストア命令のアドレッシング モード。

⚫ さまざまなロード/ストア命令のアドレッシング モード。

⚫ バッチロード/ストア命令のアドレッシングモード。

⚫ コプロセッサのロード/ストア命令のアドレッシング モード。

1. ワードおよび符号なしバイトのロード/ストア命令のアドレッシング モード

ワードおよび符号なしバイトのロード/ストア コマンドの構文形式は次のとおりです。

LDR|STR{<cond>}{B}{T} <Rd>,<addressing_mode>

上の表の「!」は、データ送信完了後にベースアドレスレジスタを更新する必要があることを示します。

2. 各種ロード/ストア命令のアドレッシングモード

このタイプのアドレッシング モードを使用する命令の構文形式は次のとおりです。

LDR|STR{<cond>}H|SH|SB|D <Rd>、<addressing_mode>

このタイプのアドレッシング モードを使用する命令には、(符号付き/符号なし) ハーフワード ロード/ストア命令、符号付きバイト ロード/ストア命令、およびダブルワード ロード/ストア命令が含まれます。

表 45.2.2.2 <addressing_mode> アドレッシングモード

3. スタック動作アドレッシングモード

スタック操作アドレッシング モードは、バルク ロード/ストア命令アドレッシング モードと非常によく似ています。ただし、スタックの操作では、プッシュ操作 (ポップ) とスタック操作 (プッシュ) ではスタックを異なる方向に調整する必要があるため、異なるアドレッシング モードを使用するためにデータがメモリに書き込まれ、メモリから読み取られます。

このタイプの命令の構文形式は次のとおりです。

LDM|STM {<amode>}{<cond>}<addressing_mode> <Rn>{!},<registers><^>

以下では、適切なアドレッシング モードを使用してデータ スタック操作を実装する方法について詳しく説明します。

スタックは、モードのアドレッシングモードの違いにより、以下の 4 種類に分けられます。

1) フルスタック: スタック ポインタはスタックの最上位要素 (最後に使用された場所) を指します。

2) 空のスタック: スタック ポインタは、最初の使用可能な要素 (最初の未使用の場所) を指します。

3) スタックの減少: スタックはメモリ アドレスの減少方向に増加します。

4) インクリメンタルスタック: スタックはメモリアドレスが増加する方向に増加します。

スタックの種類に応じて、そのアドレッシングモードは以下の 4 種類に分けられます。

1) 完全降順 FD (完全降順)。

2) 空の降順 (ED)。

3) フルインクリメント FA (フル昇順)。

4) 空の昇順 EA (空の昇順)。

表に示すように、スタック アドレッシング モードとバルク ロード/ストア命令アドレッシング モードの対応関係を示します。

バッチロード/ストア命令アドレッシングモード

バッチ ロード/ストア命令は、連続したメモリ位置から汎用レジスタ ファイルにデータをロードしたり、汎用レジスタのグループからメモリ位置にデータを保存したりします。

バッチ ロード/ストア命令のアドレッシング モードはメモリ ユニットのアドレス範囲を生成し、命令レジスタとメモリ ユニットの対応関係はこのような規則を満たします。つまり、下位番号のレジスタが下位アドレス ユニットに対応します。メモリ内で、上位番号のレジスタがメモリ ユニットに対応します。

このタイプの命令の構文形式は次のとおりです。

LDM|STM {<amode>}{<cond>}<addressing_mode> <Rn>{!},<registers><^>

コプロセッサのロード/ストア アドレッシング モード

コプロセッサのロード/ストア命令の構文形式は次のとおりです。

MCR<c> <coproc>、<opc1>、<Rt>、<CRn>、<CRm>{、<opc2>}

MRC<c> <coproc>、<opc1>、<Rt>、<CRn>、<CRm>{、<opc2>}

<c>: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

<coproc>: コプロセッサ名、範囲は p0 ~ p15。

<opc1>: コプロセッサのオペコード、範囲は 0 ~ 15。

<Rt>: ソース レジスタ。MCR 命令は Rt レジスタをコプロセッサに書き込み、MRC 命令はコプロセッサの内容を Rt レジスタに読み取ります。

<CRn>: コプロセッサのターゲット レジスタ。

<CRm>: コプロセッサ内の追加ターゲット レジスタまたはソース操作レジスタ。追加情報が必要ない場合は、C0 に設定します。そうでない場合、結果は予測できません。

<opc2>: オプションのコプロセッサ固有のオペコード。不要な場合は 0 に設定します。

CRn、opc1、CRm、opc2 などの演算に関して、CP15 コプロセッサのレジスタ レイアウトは次のとおりです。異なるコプロセッサを動作させる場合、異なる値は異なる値に対応します。

たとえば、前述のキャッシュ操作命令

コード例 45-5 ICache を有効にする

1 /******キャッシュテスト*******/

2 mrc p15,0,r1,c1,c0,0

3 orr r1, r1, #(1 << 2) // C ビットを設定してキャッシュ全体を有効にする

4 orr r1, r1, #(1 << 12) //I ビットを設定して ICache を有効にする

5 mcr p15,0,r1,c1,c0,0

6 /******テスト終了******/

他のコプロセッサを動作させる必要がある場合は、公式ドキュメントの『ARM® アーキテクチャ リファレンス マニュアル』または『Cortex-A7 MPCore テクニカル リファレンス マニュアル』を参照してください。

ARM プロセッサ命令セット

データ操作命令

データ操作命令とは、レジスタに格納されたデータを操作する命令を指します。主に、データ転送命令、算術命令、論理命令、比較およびテスト命令、乗算命令が含まれます。

S プレフィックスがデータ処理命令の前に使用される場合、命令の実行結果は CPSR のフラグ ビットに影響します。データ処理命令を表に示します。

1.MOV命令

MOV 命令は最も単純な ARM 命令であり、実行結果は数値 N をターゲット レジスタ Rd に送信します (N はレジスタまたは即値)。

MOV命令は主に初期値の設定やレジスタ間のデータ転送に使用されます。

MOV 命令は、シフト コード (shifter_operand) で表されるデータをデスティネーション レジスタ Rd に転送し、演算結果に応じて CPSR 内の対応する条件フラグを更新します。

コマンドの構文形式は次のとおりです。

MOV{<c>}{S} <Rd>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。R15 が宛先レジスタの場合、プログラム カウンタまたはフラグが変更されます。これは、リンクレジスタの内容を R15 に転送することにより、呼び出されたサブルーチンが終了した後、呼び出し元のコードに戻るために使用されます。

<shifter_operand>: Rd レジスタに転送されるデータ (即値、レジスタ、またはシフト演算によって取得された命令) 例:

コード例 45-6 の移動例

1 mov r0, r0 ; R0=R0 NOP 命令

2 mov r0、r0、lsl#3 ; R0=R0*8

3 mov pc, lr ; 呼び出し元への終了、通常の関数の戻りに使用、PC は R15

4 movs pc, lr ; 呼び出し元を終了し、関数の異常な戻りに使用されるフラグを復元します。

MOV 命令は主に次の機能を実行します。

⚫ あるレジスタから別のレジスタにデータを転送します。

⚫ 定数値をレジスタに転送します。

⚫ PC(R15)をデスティネーションレジスタとして使用すると、プログラムジャンプが実現できます。「MOV PC, LR」のように、この種のジャンプは命令「B, BL」の代わりにサブルーチンの呼び出しとサブルーチンからの復帰を実現できます。

⚫ PC がターゲット レジスタとして使用され、命令で S ビットが設定されている場合、命令はジャンプ操作の実行中に現在のプロセッサ モードの SPSR レジスタの内容を CPSR にコピーします。この命令「MOVS PC LR」は、特定の異常割り込みからの復帰を実現することができます。

MVN命令

MVN は、Move Negative コマンドです。オペランドの補数を宛先レジスタに転送します。

MVN 命令は主に、負の数をレジスタに転送したり、ビット マスクを生成したりするために使用されます。

MVN 命令は、shifter_operand で表されるデータの 1 の補数をデスティネーション レジスタ Rd に転送し、演算結果に応じて CPSR 内の対応する条件フラグを更新します。

コマンドの構文形式は次のとおりです。

MVN{<c>}{S} <Rd>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<shifter_operand>: Rd レジスタに転送されるデータ。即値、レジスタ、またはシフト演算を通じて取得することができます。これは算術演算ではなく論理 NOT 演算であり、この否定値に 1 を加えたものが負の値になります。

コマンド例:

コード例 45-7 mvn の例

1 mvn r0、#4 ; r0 = -5

2 mvn r0、#0 ; r0 = -1

MVN 命令は主に次の機能を実行します。

⚫ 負の数をレジスタに転送します。

⚫ ビットマスク(Bit Mask)を生成します。

⚫ 数値の 1 の補数を求めます。

AND命令

AND 命令は、shifter_operand で表される値とレジスタ Rn の値のビット単位の AND 演算を実行し、結果をターゲット レジスタ Rd に保存し、演算結果に従って CPSR レジスタを更新します。

コマンドの構文形式は次のとおりです。

AND{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 最初のオペランド レジスタ。

<shifter_operand>: Rn レジスタと AND 演算されるデータ

コマンド例:

コード例 45-8 とその例

1 and r0, r0, #3 ; ビット 0 と 1 を r0 に保持し、残りを破棄します。

2 と r2,r1,r3 ;r2 = r1&r3

3 ands r0,r0,#0x01 ;r0 = r0&0x01、最下位ビットのデータを取り出す

ORR命令

ORR (Logical OR) は論理和演算命令で、第 2 ソースオペランドshifter_operand の値とレジスタ Rn の値に対してビット単位の「論理和」演算を実行し、結果を Rd に保存します。

コマンドの構文形式は次のとおりです。

ORR{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: デスティネーションオペランド

<Rn>: 最初のオペランド。

<shifter_operand>: Rn と論理和をとる数値

コマンド例:

コード例 45-9 または例

1 orr r0, r0, #3 ; r0 のビット 0 と 1 を設定

2 orr r0, r0, #0x0f ; r0の下位4ビットを1に設定

3 ; orr 命令を使用して、r2 の上位 8 ビットを r3 の下位 8 ビットに移動します。

4 mov r1、r2、lsr #4

5 または r3、r1、r3、lsl #8

BICビットクリア命令

BIC (Bit Clear) ビットクリア命令、レジスタ Rn の値、および第 2 ソースオペランドの値shifter_operand のビットごとの反転コード

「論理積」演算を行い、結果をRdに保存します。

コマンドの構文形式は次のとおりです。

BIC{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: デスティネーションオペランド

<Rn>: 最初のオペランド。

<shifter_operand>: 負のコードと Rn は「論理 AND」演算を実行します

コマンド例:

コード例 45-10 ビックの例

1 bic r0, r0, #0x1011 ; r0 のビット 12、4、0 をクリアし、残りは変更しない

2 bic r1, r2, r3 ; r3 と r2 で「論理 AND」演算を実行し、結果を r1 に保存します

EOR命令

EOR (排他的 OR) 命令は、レジスタ Rn の値とshifter_operand の値に対してビット単位の「排他的 OR」演算を実行し、実行結果をデスティネーション レジスタ Rd に格納し、CPSR 内の対応する条件フラグを更新します。命令の実行結果。

コマンドの構文形式は次のとおりです。

EOR{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 最初のオペランド レジスタ。

<shifter_operand>: Rn レジスタと XOR 演算されるデータ

コマンド例:

コード例 45-11 eor の例

1 eor r0, r0, #3 ; r0 のビット 0 と 1 を反転します

2 eor r1, r1, #0x0f ; r1 の下位 4 ビットを反転します

3 eor r2,r1,r0 ;r2=r1∧r0

4 eors r0,r5,#0x01 ;r0=r5∧0x01 はフラグビットに影響します

SUB命令

SUB (減算) 命令は、shifter_operand で表される値をレジスタ Rn から減算し、結果を宛先レジスタ Rd に保存します。

、命令の実行結果に応じて、CPSR の対応するフラグ ビットを設定します。

コマンドの構文形式は次のとおりです。

SUB{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 減数。

<shifter_operand>: 減数

コマンド例:

コード例 45-12 のサブ例

1 サブルーチン r0、r1、r2 ;r0 = r1−r2

2 サブルーチン r0、r1、#256 ;r0 = r1−256

3 サブルーチン r0, r2, r3,lsl#1 ;r0 = r2−(r3<<1)

RSB命令

RSB (逆減算) 命令は、レジスタshifter_operandからRnで表される値を減算し、結果をターゲットレジスタに保存します。

レジスタRdを設定し、命令の実行結果に応じてCPSRの対応するフラグビットをセットします。

コマンドの構文形式は次のとおりです。

RSB{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 減数。

<shifter_operand>: 減数

コマンド例:

次の一連の命令は 64 ビット値を否定します。64 ビットの数値はレジスタ R0 と R1 に配置され、その負の数値は R2 と R3 に配置されます。R0 と R2 では 32 ビット値が低くなります。

コード例 45-13 RSB の例

1 RSBS r2、r0、#0

2 rsc r3、r1、#0

SBCコマンド

SBC (キャリー付き減算) 命令は、オペランドが 32 ビットより大きい場合に減算を実行するために使用されます。この命令は、レジスタRnからshifter_operandで表される値を減算し、レジスタCPSRのC条件フラグの反転コード[NOT(キャリーフラグ)]を減算し、その結果をターゲットレジスタRdに保存し、実行に従って命令の結果 CPSR の対応するフラグ ビットを設定します。

コマンドの構文形式は次のとおりです。

SBC{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 減数。

<shifter_operand>: 減数

コマンド例:

次のプログラムは、SBC を使用して 64 ビット減算 (R1, R0)-(R3, R2) を実装し、結果は (R1, R0) に格納されます。

コード例 45-14 sbc の例

1 サブ r0、r0、r2

2 sbcs r1、r1、r3

0.RSCコマンド

RSC(キャリー付きリバース減算)命令は、レジスタshifter_operandからRnで表される値を減算し、レジスタCPSRのC条件フラグの反転コード[NOT(キャリーフラグ)]を減算し、結果をターゲットレジスタに保存します。 Rd、命令の実行結果に応じて、CPSR の対応するフラグ ビットを設定します。

コマンドの構文形式は次のとおりです。

RSC{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 減数。

<shifter_operand>: 減数

コマンド例:

以下のプログラムは、RSC 命令を使用して 64 ビット値の負の値を求めます。

コード例 45-15 rsc の例

1 RSBS r2、r0、#0

2 rsc r3、r1、#0

ADD命令

ADD命令は、レジスタshifter_operandの値をRnで表される値に加算し、その結果をターゲットレジスタRdに保存し、命令の実行結果に従ってCPSRの対応するフラグビットを設定します。

コマンドの構文形式は次のとおりです。

ADD{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 最初のオペランド。

<shifter_operand>: 加算する数値

コマンド例:

例コード 45-16 例を追加

1 r0、r1、r2 を追加します。r0 = r1 + r2

2 r0、r1、#256 を追加します。r0 = r1 + 256

3 r0、r2、r3、lsl#1 を追加します。r0 = r2 + (r3 << 1)

ADC命令

ADC命令は、レジスタshifter_operandの値をRnで表される値に加え、CPSRのC条件フラグの値を加算し、結果をターゲットレジスタRdに保存し、命令の実行結果に従ってCPSRの対応するフラグを設定します。指示。

コマンドの構文形式は次のとおりです。

ADC{<c>}{S} <Rd>,<Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 最初のオペランド。

<shifter_operand>: 加算する数値

コマンド例:

ADC 命令は 2 つのオペランドを加算し、結果をデスティネーション レジスタに置きます。キャリー フラグを使用するため、32 ビットを超える加算を行うことができます。次の例では、2 つの 128 ビット数値を加算します。

128 ビットの結果: レジスタ R0、R1、R2、および R3。

最初の 128 ビット番号: レジスタ R4、R5、R6、および R7。

2 番目の 128 ビット数値: レジスタ R8、R9、R10、および R11。

コード例 45-17 adc の例

1 r0、r4、r8 を追加; 下位ワードを追加

2 adcs r1、r5、r9 ; キャリー付きで次のワードを追加

3 adcs r2、r6、r10 ; キャリー付きで 3 番目のワードを追加

4 adcs r3、r7、r11 ; キャリー付きで上位ワードを追加

CMP命令

CMP(比較)命令は、レジスタRnの値からshifter_operandの値を減算し、演算結果に応じてCPSRの対応する条件フラグを更新します。これにより、後続の命令は、対応する条件フラグに従って実行するかどうかを判断できます。 。

コマンドの構文形式は次のとおりです。

CMP{<c>} <Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

<Rn>: 最初のオペランド。

<shifter_operand>: 比較の数

コマンド例:

CMP 命令を使用すると、あるレジスタの内容を別のレジスタの内容または即値と比較し、ステータス フラグを変更して条件付き実行を行うことができます。減算を行いますが、結果を保存する代わりに、フラグ ビットを正しく変更します。フラグ ビットは、オペランド 1 とオペランド 2 の比較結果を示します (値は、より大きい、小さい、または等しい場合があります)。オペランド 1 がオペランド 2 より大きい場合、後続のオペランドには GT サフィックスが付きます

コマンドが実行されます。

どうやら、CMP はステータス フラグを変更するために S サフィックスを明示的に指定する必要はありません。

コード例 45-18 cmp の例

1 cmp r1, #10 ; r1 と即値 10 が等しいかどうかを比較します。

カエルループ2個

上記の例からわかるように、CMP 命令と SUBS 命令の違いは、CMP 命令は演算結果を保存しないことです。2 つのデータのサイズを判断する場合、CMP 命令とそれに対応するコンディション コードがよく使用されます。動作します。

CMNコマンド

CMN (Compare Negative) 命令は、レジスタ Rn の値からshifter_operand の負の値を減算し、演算結果に従って CPSR の対応する条件フラグ ビットを更新します。これにより、後続の命令は、対応する条件に従って実行するかどうかを判断できます。状態フラグ。

コマンドの構文形式は次のとおりです。

CMN{<c>} <Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c> を無視した場合、命令は無条件に実行されます。

<Rn>: 最初のオペランド。

<shifter_operand>: 比較の数

コマンド例:

CMN 命令は、レジスタ Rn 内の値をshifter_operand によって表される値に加算し、加算の結果に従って CPSR 内の対応する条件フラグを設定します。レジスタ Rn の値に CPSR の条件フラグに対するshifter_operand の演算結果を加えた効果は、レジスタ Rn の値の逆から CPSR の条件フラグに対するshifter_operand の演算結果を引いたものとは若干異なります。

次のコマンドは、R0 の値に 1 を加算し、R0 が 1 の補数であるかどうかを判断し、1 の補数である場合は Z を設定します。

コード例 45-19 cmn の例

1 cmn r0、#1

TSTテストコマンド

TST (テスト) テスト命令は、レジスタの値と値を比較するために使用されます。条件フラグは、2 つのオペランドの「論理積」の結果に従って設定されます。

TST{<c>} <Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

<Rn>: 最初のオペランド。

<shifter_operand>: 比較の数

コマンド例:

次の命令は、ビット 0 が R0 に設定されているかどうかをテストします。

コード例 45-20 tst の例

1 tst r7, #0x4 ; r7 レジスタの値の 2 番目のビットが設定されているかどうかをテストします

2 addeq r6, r7 ; 設定されている場合は、r6+r7 を実行します

3 r8、r7 を追加します。設定されていない場合は、r8+r7 を実行します。

TST 命令は、デスティネーション レジスタに配置される結果を生成しないという点で CMP 命令に似ています。代わりに、指定された 2 つのオペランドを操作し、結果をステータス フラグに反映します。TST 命令を使用して、特定のビットが設定されているかどうかを確認します。オペランド 1 はテストするデータ ワード、オペランド 2 はビットマスクです。テスト後、一致する場合は Z フラグが設定され、一致しない場合はクリアされます。CMP 命令と同様に、この命令には S サフィックスを指定する必要はありません。

TEQコマンド

TEQ (Test Equivalence) 命令は、レジスタの値と算術値を比較するために使用されます。条件フラグは、2 つのオペランドの「排他的論理和」の結果に従って設定されます。これにより、後続の命令は、対応する条件フラグに従って実行するかどうかを判断できます。

コマンドの構文形式は次のとおりです。

TEQ{<c>} <Rn>,<shifter_operand>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

<Rn>: 最初のオペランド。

<shifter_operand>: 比較の数。

コマンド例:

コード例 45-21 teq の例

1 teq r0, r1 ; r0 と r1 は等しい

2 addeq r0, r0, #1 ; r0==r1、eq が true の場合、r1=r1+1

乗算命令

ARM 乗算命令は 2 つのデータの乗算を実行します。2 つの 32 ビット 2 進数を乗算した結果は 64 ビットの積になります。ARM の一部のプロセッサ バージョンでは、積の結果が 2 つの別々のレジスタに格納されます。他のバージョンでは、レジスタに最下位 32 ビットのみが格納されます。プロセッサのバージョンに関係なく、積を継続的に累積して合計を求める積和演算命令が存在します。また、符号付きの数値と符号なしの数値の両方を使用できます。結果の最下位ビットは、符号付き数値でも符号なし数値でも同じです。したがって、32 ビットの結果のみを保持する乗算命令の場合、符号付きの場合と符号なしの場合を区別する必要はありません。

さまざまな乗算命令の機能を表に示します。

例証します:

1) 「RdHi:RdLo」は、RdHi (最上位 32 ビット) と RdLo (最下位 32 ビット) の 64 ビット連結です。

数値「[31:0]」は、結果の最下位 32 ビットのみを選択します。

2) 単純な代入は「:=」で表します。

3) 累積(右を左に加算)は「+=」で示されます。

4) 各乗算命令のビット S (以下の特定の命令の構文形式を参照) は、以下の結果を生成する条件コードの設定を制御します。

1) 32 ビットの結果を生成する命令形式の場合は、フラグ ビット N を Rd の 31 番目のビットの値に設定します; 長い結果を生成する命令形式の場合

コマンド形式では、RdHi の 31 ビット目の値に設定します。

2) 32 ビットの結果を生成する命令形式の場合、Rd が 0 に等しい場合、フラグ ビット Z が設定されます。長い結果を生成する命令形式の場合、RdHi と RdLo が両方とも 0 の場合、フラグ ビット Z が設定されます。 。

3) フラグビット C を意味のない値に設定します。

4) フラグビット V は変化しません。

 MUL命令

MUL (乗算) 32 ビット乗算命令は、Rm と Rs の値を乗算し、結果の下位 32 ビットが Rd に格納されます。

コマンドの構文形式は次のとおりです。 

MUL{<c>}{S} <Rd>,<Rm>,<Rs>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rn>: 最初のオペランド。

<Rs>: Rn に乗算する数値

コマンド例:

コード例 45-22 mul の例

1 乗 r1、r2、r3 ;r1 = r2 × r3

2 つの乗算 r0、r3、r7 ;r0 = r3 x r7

MLA命令

MLA (Multiply Accumulate) 32 ビット積和命令は、Rm と Rs の値を乗算し、その積を 3 番目のオペランドに加算し、結果の下位 32 ビットを Rd に保存します。

コマンドの構文形式は次のとおりです。

MLA{<c>}{S} <Rd>,<Rm>,<Rs>,<Rn>

{<c>}: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rd>: 宛先レジスタ。

<Rm>: 最初の乗数。

<Rs>: 2 番目の乗数。

<Rn>: Rm と Rs の積に加算します。

コマンド例:

次の命令は、R1 = R2×R3 + R0 の演算を完了します。

コード例 45-23 mla の例

1ml r1、r2、r3、r0

UMULL命令

UMULL (Unsigned Multiply Long) は、64 ビットの符号なし乗算命令です。Rm と Rs の値に符号なしの数値を乗算し、結果の下位 32 ビットを RdLo に保存し、上位 32 ビットを RdHi に保存します。

コマンドの構文形式は次のとおりです。

UMULL{<c>}{S} <RdLo>、<RdHi>、<Rm>、<Rs>

{<c>}: 命令実行の条件コード。<c> を無視した場合、命令は無条件に実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rm>: 最初の乗数。

<Rs>: 2 番目の乗数

< RdHi >: Rm と Rs の積の上位 32 ビット

< RdLo >: Rm と Rs の積の下位 32 ビット

コマンド例:

コード例 45-24 umull の例

1 r0、r1、r5、r8 を返します。(R1,R0) = R5 × R8

UMLAL命令

UMLAL (Unsigned Multiply Accumulate Long) は、64 ビットの符号なし Long 積和演算命令です。この命令は、Rm と Rs の値を符号なしの数値として乗算し、64 ビットの積を RdHi と RdLo に加算し、結果の下位 32 ビットを RdLo に保存し、上位 32 ビットを RdHi に保存します。

コマンドの構文形式は次のとおりです。

UMALL{<c>}{S} <RdLo>、<RdHi>、<Rm>、<Rs>

{<c>}: 命令実行の条件コード。<c> を無視した場合、命令は無条件に実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rm>: 最初の乗数。

<Rs>: 2 番目の乗数

<RdHi>: Rm と Rs の積の上位 32 ビットを加算します。

<RdLo>: Rm と Rs の積の下位 32 ビットを加算します。

コマンド例:

コード例 45-25 umral の例

1 ウムラル r0, r1, r5,r8 ;(r1,r0) = r5 × r8+(r1,r0)

SMULL命令

SMULL (Signed Multiply Long) は、64 ビットの符号付き Long 乗算命令です。この命令は、Rm と Rs の値に符号付きの数値を乗算し、結果の下位 32 ビットが RdLo に格納され、上位 32 ビットが RdHi に格納されます。

コマンドの構文形式は次のとおりです。

SMULL{<c>}{S} <RdLo>、<RdHi>、<Rm>、<Rs>

{<c>}: 命令実行の条件コード。<c> を無視した場合、命令は無条件に実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rm>: 最初の乗数。

<Rs>: 2 番目の乗数

< RdHi >: Rm と Rs の積の上位 32 ビット

< RdLo >: Rm と Rs の積の下位 32 ビット

コマンド例:

コード例 45-26 smull の例

1 つの小さい r2、r3、r7、r6 ;(r3,r2) = r7 × r6

SMLAL命令

SMLAL (Signed Multiply Accumulate Long) は、64 ビットの符号付き Long 積和演算命令です。この命令は、Rm と Rs の値を符号付き数値として乗算し、64 ビットの積を RdHi と RdLo に加算し、結果の下位 32 ビットを RdLo に保存し、上位 32 ビットを RdHi に保存します。

真ん中。

コマンドの構文形式は次のとおりです。

SMLAL{<c>}{S} <RdLo>、<RdHi>、<Rm>、<Rs>

{<c>}: 命令実行の条件コード。<c> を無視した場合、命令は無条件に実行されます。

{S}: 命令の操作が CPSR に影響するかどうかを決定します。

<Rm>: 最初の乗数。

<Rs>: 2 番目の乗数

<RdHi>: Rm と Rs の積の上位 32 ビットを加算します。

<RdLo>: Rm と Rs の積の下位 32 ビットを加算します。

コマンド例:

コード例 45-27 smlal の例

1 小 r2、r3、r7、r6 ;(r3,r2)=r7×r6+(r3,r2)

ロード/ストア コマンド

ロード/ストア メモリ アクセス命令は、ARM レジスタとメモリの間でデータを転送します。ARM 命令には 3 つの基本的なデータ転送命令があります。

⚫ 単一レジスタのロード/ストア命令

これらの命令は、ARM レジスタとメモリ間で単一のデータ項目を移動するためのより柔軟な手段を提供します。データ項目はバイトにすることができます。

16 ビットのハーフワードまたは 32 ビットのワード。

⚫ マルチレジスタのロード/ストアメモリアクセス命令

これらの命令は単一レジスタ転送命令よりも柔軟性に劣りますが、大量のデータをより効率的に転送できます。これらは、プロセスの開始と終了、作業レジスタの保存と復元、メモリ内のデータ ブロックのコピーに使用されます。

⚫ 単一レジスタスワップ命令

これらの命令により、レジスタとメモリ内の値を交換できるようになり、単一の命令でロード/ストア操作を効果的に実行できます。ユーザーレベルのプログラミングではほとんど使用されません。その主な目的は、マルチプロセッサ システムにセマフォ (セマフォ) 操作を実装して、共通のデータ構造が同時にアクセスされないようにすることです。

1. 単一レジスタのロード/ストア命令

LDR命令

LDR 命令は、32 ビット ワードをメモリからデスティネーション レジスタに読み取るために使用されます。

コマンドの構文形式は次のとおりです。

LDR{<c>} <Rd>,<addr_mode>

コマンド例:

コード例 45-28 ldr の例

1 ldr r1,[r0,#0x12] ; アドレス r0+12 のデータを読み出し、r1 に保存します (r0 の値は変更されません)。

2 ldr r1,[r0] ; アドレス r0 のデータを読み取り、r1 (ゼロオフセット) に保存します。

3 ldr r1,[r0,r2] ; r0+r2のアドレスのデータを読み出し、r1に保存します(r0の値は変化しません)

4 ldr r1,[r0,r2,lsl #2] ;r0+r2×4のアドレスのデータを読み出し、r1に保存(r0、r2の値はそのまま)

5 ldr pc,[pc, #0x18] ;プログラムを pc+0x18 にジャンプします

6 ldr rd,label ;label はプログラムのラベルであり、ラベルは現在の命令の -4 ~ 4kb の範囲内にある必要があります

7 ldr rd,[rn],#0x04 ;rnの値は送信データの格納アドレスとして使用されます。データ転送後、オフセット0x04とrn

結果を追加して rn に書き込みます。rnはr15にすることはできません

STRコマンド

STR 命令は、命令で指定されたメモリ ユニットに 32 ビット ワード データを書き込むために使用されます。

コマンドの構文形式は次のとおりです。

STR{<c>} <Rd>,<addr_mode>

コマンド例:

サンプルコード 45-29 strデータライトバック

1 ldr r0、=0xE0200000

2 LDR r1、=0x00002222

3 str r1、[r0、#0x20]

LDRB命令

LDRB 命令は、addr_mode で決まるアドレスモードに従い、命令内でターゲットレジスタ Rd に 1 バイト (8 ビット) を読み込みます。

コマンドの構文形式は次のとおりです。

LDRB{<c>} <Rd>、<addr_mode>

STRB命令

STRB 命令は、指定されたバイト (8 ビット) をレジスタから取得し、それをレジスタの下位 8 ビットに置き、レジスタの上位ビットを 0 で埋めます。

コマンドの構文形式は次のとおりです。

STRB{<c>} <Rd>,<addr_mode>

) LDRH命令

LDRH 命令は、16 ビットのハーフワードをメモリから宛先レジスタに読み取るために使用されます。

命令のメモリアドレスがニブルアライメントされていない場合、命令の実行結果は予測できません。

コマンドの構文形式は次のとおりです。

LDRH{<c>} <Rd>,<addr_mode>

STRH命令

STRH 命令は、指定された 16 ビットのハーフワードをレジスタから取得し、それをレジスタの下位 16 ビットに置き、レジスタの上位ビットを 0 で埋めます。

コマンドの構文形式は次のとおりです。

STRH{<c>} <Rd>,<addr_mode>

マルチレジスタロード/ストアメモリアクセス命令

マルチレジスタ ロード/ストア メモリ アクセス命令は、バルク ロード/ストア命令とも呼ばれ、レジスタのグループと連続メモリ ユニットの間でデータを転送できます。LDM は複数のレジスタをロードするために使用され、STM は複数のレジスタを保存するために使用されます。マルチレジスタのロード/ストア メモリ アクセス命令を使用すると、1 つの命令で 16 個のレジスタのサブセットまたはすべてを転送できます。マルチレジスタのロード/ストア メモリ アクセス命令は、主にコンテキスト保護、データ レプリケーション、パラメータ転送に使用されます。複数のレジスタに対するロード/ストア メモリ アクセス命令を表に示します。

表45.3.3.2 複数レジスタ操作命令

LDM命令

LDM 命令は、連続したメモリ位置から命令で指定されたレジスタ リスト内の各レジスタにデータを読み取ります。LDM命令のレジスタリストにPCが含まれている場合、命令によりメモリから読み出されたワードデータがターゲットアドレスの値として使用され、命令実行後、ターゲットアドレスからプログラムの実行が開始されます。これにより命令のジャンプが実現します。

コマンドの構文形式は次のとおりです。

LDM{<c>}<addressing_mode> <Rn>{!}、<レジスタ>

STMコマンド

STM 命令は、命令内のレジスタ リスト内の各レジスタの値を連続メモリ ユニットに書き込みます。主に、サブルーチンに入るときのブロックデータの書き込み、データスタックの操作、関連レジスタの保存に使用されます。

コマンドの構文形式は次のとおりです。

STM{<c>}<addressing_mode> <Rn>{!}、<レジスタ>

一括データ転送命令の例

LDM/STM バルク ロード/ストア命令は、一連のレジスタと連続したメモリ ユニットの間でデータを転送できます。LDM は複数のレジスタをロードし、STM は複数のレジスタをストアします。1 つの命令で 16 個のレジスタのサブセットまたはすべてを転送できます。コマンドの形式は次のとおりです。

 LDM{c}<モード> Rn{!},regist{^}

STM{c}<モード> Rn{!},regist{^}

LDM/STM の主な用途は、サイト保護、データ複製、パラメータ転送です。以下に示すように、8 つのモードがあり、最初の 4 つはデータ ブロックの送信に使用され、最後の 4 つはスタック操作に使用されます。

(1) IA: 転送ごとにアドレスに 4 を加算します。

(2) IB: 各送信前にアドレスに 4 を加算します。

(3) DA: アドレスは転送ごとに 4 ずつデクリメントされます。

(4) DB: 各転送の前にアドレスから 4 を減算します。

(5) FD: フルデクリメントスタック。

(6) ED: 空の増分スタック。

(7) FA: フル増分スタック。

(8) EA: 空の増分スタック。

このうち、レジスタ Rn は送信データの先頭アドレスを含むベース アドレス レジスタであり、Rn を R15 にすることはできません。サフィックス「!」は最後のアドレスが Rn に書き戻されることを示します。レジスタ リストreglist には複数のレジスタまたはレジスタ範囲を含めることができます。{R1、R2、R6~R9} のように区切るには「,」を使用します。レジスタは昇順に配置されます。接尾辞「^」は使用できません。ユーザーモードで使用されますが、システムモードでのみ使用できます。PC が LDM 命令レジスタ リストに含まれている場合、通常のマルチレジスタ転送に加えて、SPSR を CPSR にコピーします。これは、例外処理の戻りに使用できます。データ転送には接尾辞「^」を使用し、レジスタ リストには PC を使用する場合は含まれません。 、現在のモード レジスタではなく、ユーザー モード レジスタがロード/ストアされます。

サンプルコード 45-30 バルクデータ転送命令

1 LDMIA R0!,{R3~R9} ; R0 が指すアドレスにマルチワードデータをロードし、R3~R9 に保存し、R0 の値を更新します

2 STMIA R1!,{R3~R9} ; R3~R9のデータをR1の指すアドレスに格納し、R1の値を更新します

3 STMFD SP!,{R0~R7,LR} ; サイト上に保存、R0~R7、LRをスタックにプッシュ

4 LDMFD SP!,{R0~R7,PC}^ ;シーンを復元、異常処理で復帰

データをコピーするときは、まずソース データ ポインタを設定し、次にブロック コピー アドレッシング命令 LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB を使用して読み取りと保存を行います。スタック操作を実行するときは、まずスタック ポインターを設定し、通常は SP を使用してから、スタック アドレス指定命令 STMFD/LDMFD、STMED/LDMED、STMEA/LDMEA を使用してスタック操作を実装する必要があります。データがベース レジスタのアドレスの上か下に格納されているか、アドレスが最初の値が格納される前か後か、表に示すように、増加または減少します。

LDM/STM を使用したデータ レプリケーション。

コード例 45-31 データのレプリケーション

1 LDR R0,=SrcData ; ソースデータアドレスを設定

2 LDR R1,=DstData ; ターゲットアドレスを設定

3 LDMIA R0,{R2~R9} ; 8ワードのデータをレジスタR2~R9にロードします

4 STMIA R1, {R2~R9} ; レジスタ R2~R9 をターゲットアドレスにストアします

LDM/STM は、サブルーチンや例外処理でよく使用されるフィールド レジスタ保護に使用します。

コード例 45-32 サイトのセキュリティ保護

1 送信バイト:

2 STMFD SP!,{R0~R7,LR} ;レジスタプッシュ保護

3 ...

4 BL DELAY ; DELAYサブルーチンを呼び出します

5 ...

6 LDMFD SP!,{R0~R7,PC} ;レジスタを復元してリターン

単一のデータ交換命令

スワップ命令はロード/ストア命令の特殊なケースであり、レジスタ位置の内容をレジスタの内容と交換します。交換命令はアトミック操作 (Atomic Operation) です。つまり、連続的なバス操作でストレージ ユニットの読み取り/書き込みを行い、操作中に他の命令がストレージ ユニットを読み取り/書き込みできないようにします。交換手順を表に示します。

SWPワードスワップ命令

SWP 命令は、メモリ内のワード単位を指定したレジスタの値と交換するために使用されます。演算プロセスは次のとおりです。メモリ ユニットのアドレスがレジスタ <Rn> に格納されていると仮定すると、命令は <Rn> のデータを宛先レジスタ Rd に読み取り、同時に別のレジスタの内容を書き込みます。 <Rm>をメモリユニットに挿入します。

<Rd> と <Rm> が同じレジスタの場合、命令はレジスタとメモリユニットの内容を交換します。

コマンドの構文形式は次のとおりです。

SWP{<c>} <Rd>,<Rm>,[<Rn>]

バイト単位を指定したレジスタの下位 8 ビット値と交換し、演算処理は以下のようになります。 レジスタ <Rn> にメモリ単位のアドレスが格納されているとして、<Rn> のデータを読み出します。 > を宛先レジスタ Rd に書き込み、レジスタ Rd の値を上位 24 ビットを 0 に設定し、別のレジスタ <Rm> の下位 8 ビットをこのメモリ バイト単位に書き込みます。<Rd>と<Rm>が同じレジスタの場合、レジスタの下位8ビットの内容とメモリバイト単位の内容を交換します。

コマンドの構文形式は次のとおりです。

SWP{<c>}B <Rd>,<Rm>,[<Rn>]

コマンド例:

コード例 45-33 swp コマンドの例

1 SWP R1, R1, [R0] ; R1 の内容を R0 が指すストレージ ユニットの内容と交換します。

2 SWPB R1,R2,[R0] ;R0 が指すストレージユニットから 1 バイトのデータを R1 に読み取り (上位 24 ビットはクリアされます)、R2 の内容をメモリユニットに書き込みます (最下位バイトが有効)。 SWP 命令を使用すると、セマフォ操作を簡単に実行できます。

ジャンプ命令

ジャンプ (B) 命令とジャンプ リンク (BL) 命令は、命令が実行される順序を変更する標準的な方法です。ARM は通常、命令をワード アドレス順に実行し、必要に応じて条件付き実行を使用して特定の命令をスキップします。プログラムを順不同で実行する必要がある場合は、制御フロー命令を使用してプログラム カウンターを変更します。転送および転送接続命令は標準的な方法ですが、特定の状況でこれを実現する方法は他にもいくつかあります。ジャンプ命令は、プログラムの実行フローを変更したり、サブルーチンを呼び出したりします。この命令により、プログラムでサブルーチン、if-then-else 構造、およびループを使用できるようになります。実行フローが変更されると、プログラム カウンター (PC) が新しいアドレスを指すようになります。

命令ジャンプを実現するもう 1 つの方法は、ターゲット アドレス値を PC レジスタに直接書き込むことにより、4GB アドレス空間で任意のジャンプを実現する方法であり、このジャンプ命令はロング ジャンプとも呼ばれます。ロングジャンプ命令の前に「MOV LR」や「MOV PC」などの命令を使用すると、将来返されるアドレス値を保存し、4GBのアドレス空間でのサブルーチンコールを実現できます。

1.ジャンプ命令Bとコネクション付きジャンプ命令BL

ジャンプ命令Bは、指定されたアドレスにプログラムをジャンプさせて実行する命令である。コネクション付きジャンプ命令BLは、次の命令のアドレスをR14(リターンアドレスコネクションレジスタLR)レジスタにコピーし、指定されたアドレスにジャンプしてプログラムを実行します。これら 2 つの命令とターゲット アドレスの命令は ARM 命令セットに属している必要があることに注意してください。どちらの命令も、CPSR の条件フラグ ビットの値に従って命令を実行するかどうかを決定できます。

コマンドの構文形式は次のとおりです。

B{L}{<c>} <ターゲットアドレス>

BL 命令は、サブルーチン呼び出しを実装するために使用されます。サブルーチンリターンはLRレジスタの値をPCレジスタにコピーすることで実現できます。サブルーチンリターンは以下の3命令で実現できます。

1) BX R14 (アーキテクチャが BX 命令をサポートしている場合)。

2) MOV PC、R14。

3) サブルーチンのエントリポイントでプッシュ命令を使用する場合:

STMFD R13!,{<レジスタ>,R14}

次のコマンドを使用できます。

LDMFD R13!,{<レジスタ>,PC} 

サブルーチンのリターンアドレスをPCに入力します。

ARM アセンブラは、次の手順で命令エンコーディング内の signed_immed_24 を計算します。

1) PC レジスタの値をこのジャンプ命令のベースアドレス値として使用します。

2) ジャンプ先アドレスから上記ジャンプベースアドレスを減算し、バイトオフセットを生成します。ARM 命令はワード アラインメントされているため、このバイト オフセットは 4 の倍数になります。

3) 上記で生成されたバイト オフセットが -33 554 432 ~ +33 554 430 を超える場合、アセンブラごとに異なるコード生成戦略が使用されます。それ以外の場合は、命令コードワードの signed_immed_24 を上記のバイト オフセットのビット [25:2] に設定します。

プログラム例:

プログラムは LABLE ラベルにジャンプします。

コード例 45-34 はラベルにジャンプします

1bラベル

2 r1、r2、#4 を追加

3 r3、r2、#8 を追加

4 サブ r3、r3、r1

5ラベル:

6 サブ r1、r2、#8

絶対アドレスへジャンプ

コード例 45-35 は絶対アドレスにジャンプします 

1 b 0x1234

サブルーチン関数の実行にジャンプし、同時に現在の PC 値を LR に保存します。

サンプルコード 45-36 サブルーチンジャンプ 

1 つの BL 機能

ジャンプ命令を使用して無限ループを作成します。

コード例 45-37 無限ループ 

1 ループ:

2 r1、r2、#4 を追加

3 r3、r2、#8 を追加

4 サブ r3、r3、r1

5bループ

ジャンプを使用してプログラム本体を 10 回ループします。

コード例 45-38 有限ループ 

1 ムーブ r0、#10

2 ループ:

3 サブ r0、#1

4 ベンループ

条件付きサブルーチン呼び出しの例。

コード例 45-39 条件付きコール 

1 cmp r0,#5 ; r0<5 の場合

2 bllt sub1 ; その後呼び出します

3 blge sub2; それ以外の場合は sub2 を呼び出します

状態切り替え付きジャンプ命令BX

状態切り替え付きジャンプ命令(BX)は、命令内で指定されたパラメータ Rm で指定されたアドレスにプログラムをジャンプさせてプログラムを実行し、Rm の 0 ビット目を CPSR の T ビットにコピーし、bit[31:1] 』をPCに移動します。Rm の bit[0] が 1 の場合、ジャンプ時に CPSR のフラグ ビット T が自動的にセットされます。つまり、ターゲット アドレスのコードが Thumb コードとして解釈されます。Rm の bit[0] が 0 の場合、ジャンプは自動的にリセットされます。 CPSR のフラグ ビット T、つまり、ターゲット アドレス コードを ARM コードとして解釈します。

コマンドの構文形式は次のとおりです。

BX{<c>} <Rm>

Rm[1:0]=0b10 の場合、命令の実行結果は予測できません。ARM 状態では命令は 4 バイトでアラインされているためです。PC を Rm レジスタとして使用することもできますが、この使用法は推奨されません。PC が <Rm> として使用される場合、「BX PC」命令はプログラムを現在の命令の下の 2 番目の命令にジャンプして実行します。このようなジャンプは実装できますが、そのようなジャンプを実行するには次の命令を使用するのが最善です。

MOV PC, PC或ADD PC, PC, #0

コマンド例:

R0 のアドレスに分岐し、R0[0]=1 の場合、Thumb 状態に入ります。

コード例 45-40 bx 命令の例 

1 ボックス r0

接続および状態切り替え付きリンクジャンプ命令 BLX Link Exchange 付き分岐 (BLX) は、ラベルを使用して、プログラムを Thumb 状態にジャンプしたり、Thumb 状態から復帰させたりします。この命令は無条件実行命令であり、分岐レジスタの最下位ビットを使用して CPSR の T ビットを更新し、戻りアドレスを接続レジスタ LR に書き込みます。

文法形式:

BLX <ターゲット追加>

このうち、<target_add>は命令のジャンプ先アドレスです。このアドレスは次の規則に従って計算されます。

1) 命令で指定された 24 ビット オフセットを符号拡張して、32 ビットの即値を形成します。

2) 結果を 2 桁左にシフトします。

3) 結果アドレスの最初のビット (ビット [1]) にビット H (ビット [24]) が追加されます。

4) 結果をプログラムカウンタ(PC)に蓄積します。

オフセットを計算する作業は通常、ARM アセンブラによって行われます。この形式のジャンプ命令では、−32~32MB の空間のジャンプしか実現できません。2 ビット左にシフトしてワード オフセットを形成し、それがプログラム カウンタ (PC) に蓄積されます。このとき、プログラムカウンタの内容はBX命令アドレス+8バイトになります。ビット H (ビット [24]) も結果アドレスの最初のビット (ビット [1]) に追加され、ターゲット アドレスは次の Thumb 命令を実行するためのハーフワード アドレスになります。オフセットを計算する作業は通常、ARM アセンブラによって行われます。この形式のジャンプ命令では、−32~32MB の空間のジャンプしか実現できません。

コマンド例:

Thumb 状態から ARM 状態に戻るには、BX 命令を使用します。

コード例 45-41 Thumb ステータスが ARM ステータスを返す

1 つの blx 関数

状態操作命令

ARM 命令セットには、プログラム ステート レジスタ (PSR) を直接制御する 2 つの命令が用意されています。MRS 命令は CPSR または SPSR の値をレジスタに転送するために使用され、MSR は逆にレジスタの内容を CPSR または SPSR に転送します。

これら 2 つの命令を組み合わせると、CPSR および SPSR の読み取り/書き込みに使用できます。プログラムステータスレジスタ命令を表に示します。

表45.3.5.1 ステータス操作命令

コマンド構文にはフィールドと呼ばれる項目があり、制御 (C)、拡張子 (X)、ステータス (S)、およびフラグ (F) を組み合わせることができます。

1、MRS

MRS 命令は、プログラムステータスレジスタの内容を汎用レジスタに転送するために使用されます。

ARM プロセッサでは、MRS 命令のみがステータス レジスタ CPSR または SPSR を汎用レジスタに読み込むことができます。

コマンドの構文形式は次のとおりです。

MRS{c} Rd、PSR

このうち、Rd はターゲットレジスタであり、Rd をプログラムカウンタ (PC) とすることはできません。PSRはCPSRまたはSPSRです。

コマンド例:

コード例 45-42 CPSR および SPSR の読み取り 

1 mrs r1, cpsr ; cpsr ステータス レジスタを読み取り、r1 に保存します。

2 mrs r2, spsr ; spsr ステータス レジスタを読み取り、r1 に保存します。

MRS 命令は CPSR を読み出し、ALU ステータスフラグや IRQ/FIQ 割り込みの許可などを判断することができ、例外処理プログラムでは SPSR を読み出すことで例外に入る前のプロセッサの状態を特定することができます。MRS は MSR と組み合わせて使用​​され、CPSR または SPSR レジスタの読み取り-変更-書き込み操作を実現します。これを使用して、プロセッサ モードの切り替え、IRQ/FIQ 割り込みの有効化/無効化、およびその他の設定を行うことができます。また、プロセスの切り替えや異常割り込みのネストを許可する場合には、MRS命令を使用してSPSRのステータス値を読み出し、保存する必要もあります。 

MSR

ARM プロセッサでは、MSR 命令のみがステータス レジスタ CPSR または SPSR を直接設定できます。

コマンドの構文形式は次のとおりです。

MSR{c} PSR_fields、#immed_8r

MSR{c} PSR_fields、Rm

このうちPSRとはCPSRまたはSPSRのことを指します。<fields> ステータスレジスタに操作するビットを設定します。ステータス レジスタの 32 ビットは 4 つの 8 ビット フィールドに分割できます。bits[31:24] は f で表される条件フラグ ビット フィールド、bits[23:16] は s で表される状態ビット フィールド、bits[15:8] は x で表される拡張ビット フィールド、bits [7:0] は c で示される制御ビット フィールド、immed_8r はステータス レジスタの指定されたドメインに転送される即値、8 ビット、Rm はステータス レジスタの指定されたドメインに転送されるデータ ソース レジスタです。ステータスレジスタ。

コマンド例:

コード例 45-43 MSR 命令の例

1 msr cpsr,#0xd3 ;cpsr[7:0]=0xd3、管理モードに切り替えます

2 msr cpsr,r3 ;cpsr=r3

注: ステータス レジスタは特権モードでのみ変更できます。

プログラムでは、CPSR の T ビット制御ビットを MSR 命令で直接変更して ARM ステート/Thumb ステートの切り替えを実現することはできず、プロセッサ ステートの切り替えを完了するには BX 命令を使用する必要があります ( BX 命令は転送命令であり、パイプライン状態を中断し、プロセッサ状態の切り替えを実現します。MRS は MSR と組み合わせて使用​​され、CPSR または SPSR レジスタの読み取り-変更-書き込み操作を実現します。これを使用して、プロセッサ モードを切り替えたり、IRQ/FIQ 割り込み設定を有効/無効にすることができます。

プログラムステータスレジスタ命令の適用

IRQ割り込みを有効にします。

コード例 45-44 IRQ 割り込みを有効にする

1 イネーブル_irq:

2 ミスター r0、cpsr

3 ビック r0,r0,#0x80

4msr cpsr_c,r0

5 ムーブ PC、LR

IRQ割り込みを無効にします。

コード例 45-45 IRQ 割り込みを無効にする

1 disable_irq:

2 ミスター r0、cpsr

3 または r0,r0,#0x80

4msr cpsr、r0

5 ムーブ PC、LR

割り込みモードスタックを設定します。

コード例 45-46 irq モードスタック

1 msr cpsr、#0xd2

2 LDR SP、スタックVC

コプロセッサ命令

ARM アーキテクチャでは、コプロセッサを追加することで命令セットを拡張できます。最も一般的に使用されるコプロセッサは、オンチップ機能の制御に使用されるシステム コプロセッサです。たとえば、キャッシュおよびメモリ管理ユニットを制御する cp15 レジスタです。さらに、浮動小数点演算用の浮動小数点 ARM コプロセッサもあり、メーカーは必要に応じて独自の専用コプロセッサを開発することもできます。

ARM コプロセッサには、ARM の状態を制御する命令をミラーリングする命令によって状態が制御される独自の専用レジスタ セットがあります。プログラムの制御フロー命令は ARM プロセッサによって処理され、すべてのコプロセッサ命令はデータ処理とデータ転送にのみ関連します。RISC のロード/ストア システム原理によれば、データ処理命令と送信命令は明確に分離されているため、命令フォーマットが異なります。ARM プロセッサは 16 個のコプロセッサをサポートしており、各コプロセッサはプログラム実行中に ARM および他のコプロセッサ命令を無視します。コプロセッサハードウェアがそのコプロセッサ命令を実行できない場合、未定義命令例外割り込みが生成され、例外割り込み処理プロセス中にハードウェア動作をソフトウェアでシミュレートできます。システムにベクトル浮動小数点演算ユニットが含まれていない場合は、浮動小数点演算パッケージを選択してベクトル浮動小数点演算をサポートできます。

ARM コプロセッサは命令を部分的に実行してから割り込みを生成できます。これにより、ゼロ除算やオーバーフローなど、実行時に生成される例外をより適切に処理できるようになります。ただし、命令の実行の一部はコプロセッサによって行われ、ARM に対して透過的です。ARM プロセッサが実行を再開すると、例外を引き起こした命令から実行を開始します。コプロセッサの場合、コプロセッサ命令のすべてのフィールドが必ずしも使用されるわけではありません。特定のコプロセッサがどのように定義され、どのように動作するかはコプロセッサのメーカーによって完全に決定されるため、ARM コプロセッサ命令内のコプロセッサ レジスタの識別子や演算ニーモニックもさまざまな実装定義を持ちます。プログラマはマクロを使用してこれらの命令の構文形式を定義できます。

ARM コプロセッサ命令は次の 3 つのカテゴリに分類できます。

⚫ コプロセッサのデータ操作。コプロセッサのデータ操作は完全にコプロセッサの内部操作であり、コプロセッサ レジスタの状態変更を完了します。浮動小数点加算演算などでは、浮動小数点コプロセッサ内で 2 つのレジスタが加算され、その結果が 3 番目のレジスタに格納されます。このような注文には CDP 注文が含まれます。

⚫ コプロセッサのデータ転送命令。これらの命令は、レジスタからコプロセッサ レジスタにデータを読み取るか、コプロセッサ レジスタからメモリにデータをロードします。コプロセッサは独自のデータ型をサポートできるため、レジスタごとに転送されるワード数はコプロセッサに依存します。ARM プロセッサはメモリ アドレスを生成しますが、転送されるバイトはコプロセッサによって制御されます。このような命令には、LDC 命令と STC 命令が含まれます。

⚫ コプロセッサレジスタ転送命令。場合によっては、ARM プロセッサとコプロセッサの間でデータを転送する必要があります。浮動小数点コプロセッサと同様に、FIX 命令はコプロセッサ レジスタから浮動小数点データを取得し、それを整数に変換し、その整数を ARM レジスタに転送します。多くの場合、制御フローに影響を与えるために浮動小数点比較の結果を使用する必要があるため、比較結果を ARM の CPSR に渡す必要があります。このようなコプロセッサレジスタ転送命令には、MCR および MRC が含まれます。

すべてのコプロセッサ処理命令を表に示します。

表45.3.6.1 コプロセッサ動作命令

以下では、より一般的に使用される MCR および MRC コマンドの使用法を簡単に紹介します。

ARM レジスタからコプロセッサ レジスタへのデータ転送命令 MCR

コマンドの構文

MCR<c> <coproc>、<opc1>、<Rt>、<CRn>、<CRm>{、<opc2>}

<c>: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

<coproc>: コプロセッサ名、範囲は p0 ~ p15。

<opc1>: コプロセッサのオペコード、範囲は 0 ~ 15。

<Rt>: ソース レジスタ。Rt レジスタをコプロセッサに書き込みます。

<CRn>: コプロセッサのターゲット レジスタ。

<CRm>: コプロセッサ内の追加ターゲット レジスタまたはソース操作レジスタ。追加情報が必要ない場合は C0 に設定し、それ以外の場合は C0 に設定します。

結果は予測できません。

<opc2>: オプションのコプロセッサ固有のオペコード。不要な場合は 0 に設定します。

コプロセッサレジスタからARMレジスタへのデータ転送命令MRC

コマンドの構文

MRC<c> <coproc>、<opc1>、<Rt>、<CRn>、<CRm>{、<opc2>}

<c>: 命令実行の条件コード。<c>を省略した場合、命令は無条件で実行されます。

<coproc>: コプロセッサ名、範囲は p0 ~ p15。

<opc1>: コプロセッサのオペコード、範囲は 0 ~ 15。

<Rt>: ソース レジスタ。コプロセッサの内容を Rt レジスタに読み取ります。

<CRn>: コプロセッサのターゲット レジスタ。

<CRm>: コプロセッサ内の追加ターゲット レジスタまたはソース操作レジスタ。追加情報が必要ない場合は C0 に設定し、それ以外の場合は C0 に設定します。

結果は予測できません。

<opc2>: オプションのコプロセッサ固有のオペコード。不要な場合は 0 に設定します。

コマンド例

コード例 45-47 ICache を有効にする

1 /******キャッシュテスト*******/

2 mrc p15,0,r1,c1,c0,0

3 orr r1, r1, #(1 << 2) // C ビットを設定してキャッシュ全体を有効にする

4 orr r1, r1, #(1 << 12) //I ビットを設定して ICache を有効にする

5 mcr p15,0,r1,c1,c0,0

6 /******テスト終了******/

例外発生命令

ARM 命令セットには、例外を生成する 2 つの命令が用意されており、これらの命令を通じてソフトウェアで例外を実現できます。ARM の例外生成命令を表に示します。

ソフトウェア割り込み命令 (Software Interrupt、SWI) は、ユーザー モードから管理モードへの移行を実現するためにソフト割り込みを生成し、管理モードで CPSR を SPSR に保存し、実行を SPSR に転送するために使用されます。 SWI ベクトル。SWI 命令は他のモードでも使用でき、プロセッサはスーパーバイザ モードにも切り替わります。

コマンドの構文形式。

SWI{<c>} <immed_24>

コマンド例

コード例 45-48 swi 命令の例

1 swi 0 ; ソフト割り込みを生成します、割り込み番号は 0 です

2 swi 0x123456 ; ソフト割り込みを生成します。割り込みの即値は 0x123456 です。

SWI 命令を使用する場合、パラメータの受け渡しには通常次の 2 つの方法が使用されます。

以下のプログラムは、割り込み番号 12 のソフト割り込みを生成します。

コード例 45-49 swi 命令の例

1 mov r0,#34 ; 関数番号を 34 に設定します

2 swi 12 ; ソフト割り込みを生成します、割り込み番号は 12 です

次の例では、R0 を介して割り込み番号を送信し、R1 は割り込みのサブ機能番号を送信します。

コード例 45-50 swi 命令の例

1 mov r0,#12 ; ソフト割り込み番号 12 を設定

2 mov r1,#34 ; 関数番号を 34 に設定します

3 スイ 0

ARM 組み立て実験

目的

プログラムがどのように動作するかを理解する

ARM アセンブリ言語の基本的な使い方をマスターします。

アセンブリプロジェクトとシミュレーションを構築するための Eclipse 開発ツールに精通している。

実験原理

上記で説明したRAMアセンブリ言語の使用構文と機能に従って、簡単なデータ操作を実現するアセンブリプログラムを記述します。

⚫ 実行可能プログラムのコンポーネント

Linux で実行可能な Elf アプリケーションには、通常、次の部分が含まれています。

図 45-3 実行可能プログラムのコンポーネント

これには、コード セグメント、データ セグメント、初期化されていないデータ、ヒープ、スタック、いくつかの部分が含まれます。

コード セグメント: コード セグメントはメモリ内に読み取り専用でマップされます。通常、プログラムを実行するための命令を保存するために使用されます。

データセグメント: 通常、初期化された(ゼロ以外の)グローバル変数と静的ローカル変数をプログラム内に格納するために使用されます。データセグメントの開始位置はリンクロケーションファイルによって確認され、サイズはコンパイルおよびリンク時に自動的に割り当てられます。 。

未初期化データ: 通常、プログラム内で初期化されておらず 0 に初期化され、プログラムのロード時にクリアされるグローバル変数を格納するために使用されるメモリ領域。

ヒープ: 関数内で動的に割り当てられたメモリ (malloc または new) を保存します。

スタック: 関数のローカル変数 (静的に変更された変数を除く)、パラメーター、戻り値を保存します。

アセンブリ言語では、実行可能プログラムには通常、少なくともコード セグメント + データ セグメント + BSS セグメントが含まれます。

⚫ 位置依存および位置独立:

位置非依存コードは位置に依存せず、どこに配置されても正常に実行できるため、アドレスは動的で固定できません。位置関連コードは、まさに特定の場所に関連するコードであり、この特定の場所がリンク アドレスです。

⚫リンク アドレス:

プログラムがコンパイルされるとき、各オブジェクト ファイルはソース コードからコンパイルされ、最後に複数のオブジェクト ファイルがリンクされて最終的な実行可能ファイルが生成されます。リンク アドレスはリンカー、つまり実行可能プログラム内の各オブジェクト ファイルのアドレスを示します。位置。たとえば、実行可能プログラム a.out は、ao、bo、co で構成されます。最後の a.out では、誰が先頭、誰が真ん中、誰が最後なのかを指定することで決定できます。リンクアドレス。

⚫実行 アドレス:

プログラムがメモリ内で実際に実行されているときのアドレス。たとえば、CPU が命令を実行したい場合、PC に値を割り当てて対応するアドレス空間から命令をフェッチする必要があります。このアドレスが実際の実行アドレスになります。

⚫ロード アドレスとストアアドレス:

すべてのプログラムは最初にフラッシュに格納され、メモリ上で実行されますが、このときフラッシュからメモリに命令を読み出す必要があり(実行アドレス)、フラッシュのアドレスがロードアドレスとなります。

図 45-4 リンクアドレスと実行アドレスの比較

実験内容

リンカースクリプトを作成する

コード例 45-51 リンカー スクリプト

1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

2 OUTPUT_ARCH(腕)

3 エントリー(_開始)

4つのセクション

5 {

6.= 0xc2000040;

7 。= 整列(4);

8 .テキスト:

9 {

10 start.o(.text)

11 *(.text)

12 }

13.= 整列(4);

14.ロデータ:

15 { *(.rodata) }

16.= 整列(4);

17 .data :

18 { *(.data) }

19.= 整列(4);

20 .bss :

21 { *(.bss) }

22 }

Makefile コンパイル スクリプトを作成する

コード例 45-52 メイクファイル

1 SHELL=C:\Windows\System32\cmd.exe

2

3 CROSS_COMPILE = arm-none-eabi4 NAME = h_project

5

6 CPPFLAGS := -nostdlib -nostdinc -g

7 CFLAGS := -Wall -O2 -fno-builtin -g

8

9 LD = $(CROSS_COMPILE)ld

10 CC = $(CROSS_COMPILE)gcc

11 OBJCOPY = $(CROSS_COMPILE)objcopy

12 OBJDUMP = $(CROSS_COMPILE)objdump

13

14 エクスポート CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGS

15

16 個のオブジェクト := start.o

17 個すべて: $(objs)

18 $(LD) -T map.lds -o $(NAME).elf $^

19 $(OBJCOPY) -O バイナリ $(NAME).elf $(NAME).bin

20 $(OBJDUMP) -D $(NAME).elf > $(NAME).dis

21

22 %.o : %.S

23 $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c

24

25 %.o : %.c

26 $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c

27

28 クリーン:

29 rm *.o *.elf *.bin

アセンブラプログラムは次のように設計されています

コード例 45-53 アセンブリ例

1 .テキスト

2 .global_start

3 _開始:

4

5 ムーブ r0、#0x9

6 いや

7 ムーブ r1、#0x7

8

9 bl 追加サブ

10

11 ストップ:

12bストップ

13

14 追加サブ:

15 r2、r0、r1 を追加します。r2=0x9+0x7=0x10

16 サブ r3、r0、r1 ; r3=0x9-0x7=0x2

17

18 マル r4、r0、r1 ; r4=0x9*0x7=0x3f

19 ムーブ PC、lr

実験手順

1. プロジェクトのソースコードをインポートする

「既存プロジェクトのインポート」の「既存プロジェクトのインポート」を参照してください。

CD-ROM 実験ソース コード パス: [データ CD\Huaqing Vision-FS-MP1A Development Data-2020-11-06\02-Program Source Code\03-ARM System

構造とインターフェイスのテクノロジー\Cortex-A7\h_project]

2.「登録」表示ボックスを開きます

ウィンドウ -> ビューを表示 -> 登録をクリックし、

3. シングルステップシミュレーション

構成が完了したら、「 」をクリックしてシミュレーションを開始すると、「デバッグ」ボックスがポップアップ表示されます。

シングルステップシミュレーションを実行するには、「 」をクリックします。シミュレーションを確認してください。

実験現象

「 」をクリックすると、Rn レジスタの変更が表示されます。

実行をステップ実行して、R2、R3、および R4 の値の変化を確認します。

おすすめ

転載: blog.csdn.net/u014170843/article/details/130194736