命令の種類
■機械語命令(機械語命令)
CPUを直接操作する命令。マシン語に変換され、実行時にCPUに読み込まれる
例:LD、ADDA、ST、RET
■アセンブラ命令
アセンブラに対して指示をする。アセンブリ言語の命令をマシン後に変換するときに使う。開始アドレスや、ラベルを置き換える
例:START、END、DC、DS
■マクロ命令
あらかじめ用意されたプログラムを呼び出す。
例:OUT、IN
分岐命令・比例命令一覧
アセンブリ言語 CASL2 比較命令と分岐命令 | Arcanum
CASL2の分岐命令は、プログラムの流れを制御するために使用されます。分岐命令は、プログラムが特定の条件を満たしたときに実行の順序を変える重要な役割を果たします。主に2種類の分岐命令があります。
1. 条件付き分岐命令
条件付き分岐命令は、フラグレジスタ(FR)の値に基づいて分岐します。代表的な条件付き分岐命令には次のようなものがあります:
- JPL(ジャンププラス): FRのサインフラグ(SF)が0の場合、つまり正の数のときに分岐【1】。
- JMI(ジャンプマイナス): SFが1の場合、つまり負の数のときに分岐。
- JZE(ジャンプゼロ): FRのゼロフラグ(ZF)が1の場合、つまり演算結果がゼロのときに分岐。
2. 無条件分岐命令
無条件に指定したアドレスにジャンプする命令です。
- JUMP: 条件を問わず、指定されたアドレスに分岐します【3】。
これらの命令を使うことで、条件に応じたプログラムの流れを柔軟に制御できます。
命令一覧
メモリーからレジスタへデータを読み込む(LD命令)
LD命令(Load命令)は、アセンブリ言語で使用される命令の一つで、メモリからデータをレジスタに読み込むために使用されます。この命令は、プログラムの実行時に、メモリ上のデータを操作する際に頻繁に使われます。
主な特徴:
- メモリからレジスタへデータ転送: LD命令は、指定したメモリアドレスからデータをレジスタにロードします。
- 構文:
例: – 一般的な形式は次のようになります。
```
LD GR0, [0x1000] ; メモリアドレス0x1000からデータを汎用レジスタGR0にロード
LD GR0, A ;ラベルAのアドレスからデータを汎用レジスタGR0にロード
```
- 使用場面:
- メモリ上の変数を操作する際、メモリに格納されている数値やデータをレジスタに移動して計算する際に使用されます。
LD命令は非常に基本的な命令であり、ほぼすべてのアセンブリ言語に存在します。ハードウェアリソースに直接アクセスできるため、低レベルプログラミングで重要です。
レジスタからメモリへデータを書き込む(ST命令)
ST命令(Store命令)は、アセンブリ言語で使用される命令の一つで、レジスタの内容をメモリに書き込むために使用されます。これは、CPU内のレジスタに保持されたデータをメモリアドレスに保存する際に利用されます。
主な特徴:
- レジスタからメモリへのデータ転送: ST命令は、レジスタに保持されているデータを指定されたメモリアドレスに書き込みます。
- 構文:
例: – 一般的な形式は次のようになります。
```
ST GR0, [0x2000] ; 汎用レジスタGR0にあるデータをメモリアドレス0x2000に書き込む
ST GR0, A ;汎用レジスタGR0にあるデータをラベルAのアドレスに書き込む
```
- 使用場面:
- プログラムがデータを保持する必要がある場合、または処理した結果を保存する際にST命令が使われます。例えば、演算結果や一時的なデータをメモリに保存するために利用されます。
ST命令はLD(ロード)命令と対になって使用され、メモリとレジスタ間で効率的にデータをやり取りするために重要な役割を果たします。
特定のポートに指定したレジスタのデータを送信する(OUT命令)
アセンブラ言語におけるOUT命令は、特定の出力ポートにデータを送るために使用されます。通常、マイクロプロセッサやCPUが外部デバイス(ディスプレイ、プリンタ、センサなど)と通信する際に利用されます。この命令は、主にI/Oマッピングを介してハードウェアとのやり取りを行うために使われます。
基本動作
- 構文:
OUT port, A
- この例では、レジスタ
A
に格納されたデータが、指定したポートに送信されます。
- この例では、レジスタ
- ポート番号は、CPUのアドレス空間とは異なる、専用のI/Oアドレス空間の一部であり、外部デバイスに対応しています。
使用例:
MOV A, 0x12 ; レジスタAに0x12を格納
OUT 0x03, A ; ポート0x03にレジスタAのデータを送信
このように、OUT命令は、外部デバイスに対してデータを出力するための重要な役割を果たします。特に組み込みシステムやハードウェア制御の場面で頻繁に使われます。
任意のラベル名でメモリ領域を確保し、定数データをに格納する(DC命令)
DC命令(Define Constant)は、アセンブラ言語において、定数データをメモリに格納するための命令です。この命令は、特定のデータ領域に数値や文字列などの定数を保存するために使用されます。主に、プログラム中で固定値を扱う場合に活用されます。
主な特徴:
- メモリ領域の確保: DC命令は、指定された定数に対してメモリ領域を割り当て、そこにデータを格納します。
- 定数の種類: DC命令では、整数、文字列、浮動小数点数など、様々なデータ型の定数を定義できます。
- 使用例:
BUF DC 10 ; 定数10をBUFラベルのメモリに格納 CHAR DC 'ABC' ; 文字列'ABC'をCHAEラベルのメモリに格納
応用:
DC命令は、ループや固定データ参照、テーブルデータなど、頻繁にアクセスするデータの管理に使われます。また、リテラルや配列を効率的に扱う場合にも有効です。
任意のラベル名でメモリ領域のみを確保する(DS命令)
DS命令(Define Storage)は、アセンブリ言語においてメモリ領域を確保するための命令です。この命令は、変数のために一定量のメモリを予約し、データの格納に使用されます。主にプログラムで使用するRAM領域を確保するために利用され、特定の値は格納せず、単に指定されたサイズ分の領域を確保します。
主な特徴:
- メモリ確保: DS命令は、指定されたサイズ分だけのメモリ領域を確保します。
- 初期化しない: DS命令は確保するだけで、その領域に特定の初期値を設定しません。
- 構文:
- 一般的な形式は次のようになります。
BUF DS 10 ; BUFという名前のラベルで10バイトのメモリ領域を確保
- 一般的な形式は次のようになります。
- 用途: 変数やデータバッファをプログラム内で動的に管理する場合に使用されます。
DS命令は、メモリ管理が重要なシステムや組み込みプログラミングでよく利用され、プログラム内で柔軟にメモリを使用できるようにします。
指定したレジスタに別のレジスタの値や定数を符号付き加算する(ADDA命令)
ADDA命令は、アセンブリ言語における算術加算(Arithmetic Addition)を行う命令です。この命令は、2つのオペランドを加算し、その結果を指定されたレジスタに保存します。主に算術演算を行う際に使用されます。
主な特徴:
- 算術加算: ADDA命令は、指定したレジスタの内容に他の値(定数または別のレジスタの値)を加算します。
- 符号付き加算: ADDA命令は符号付きの加算を行い、オーバーフローやキャリーの状態をフラグに反映します。
- 構文:
例: – 一般的な形式は次のようになります。
```
ADDA レジスタ1, レジスタ2
```
```
ADDA R0, R1 ; R0の値にR1の値を加算し、結果をR0に保存
```
応用:
ADDA命令は、数値の計算やループ内のインデックス操作など、様々な場面で使用されます。数値の範囲を超えた場合には、フラグが設定され、エラー処理を行うことが可能です。
指定したレジスタに別のレジスタの値や定数を符号なし加算する(ADDL命令)
CASL2のADDL
命令は、論理加算(符号なし加算)を行う命令です。符号付き加算を行うADDA
命令と異なり、符号を考慮せずに処理します。主な特徴は以下の通りです。
- 命令形式:
ADDL gr, adr[, xr]
またはADDL gr1, gr2
gr
は一般レジスタを指定します。adr
はメモリアドレス、xr
はインデックスレジスタの省略可能な指定です。gr1, gr2
は2つのレジスタ間で加算を行います[2]。
- 動作: 指定されたレジスタの値とメモリもしくは他のレジスタの値を、符号を無視して加算し、その結果をレジスタに格納します。
- 用途: 符号なしデータの処理や、符号の扱いが不要な場面で利用されます。たとえば、メモリやレジスタに保存された数値を単純に足し合わせたいときに有効です。
指定したレジスタに別のレジスタの値や定数を減算する(SUBA命令)
SUBA命令(Subtract Arithmetic)は、アセンブリ言語で算術減算を行う命令です。この命令は、指定されたレジスタやメモリの値を、レジスタに格納された値から引き算し、その結果を元のレジスタに保存します。
主な特徴:
- 算術減算: SUBA命令は、符号付きの値を減算します。
- フラグの影響: SUBA命令は、減算の結果に応じてオーバーフローやキャリーフラグなどが設定され、次の処理で利用可能です。
- 構文:
例: – 一般的な形式は次のようになります。
```
SUBA レジスタ1, レジスタ2
```
```
SUBA R0, R1 ; R0からR1の値を引き、結果をR0に保存
```
応用:
SUBA命令は、数値の計算やカウンタの減少、インデックスの操作など、算術処理を必要とする場面で頻繁に使われます。符号付きの減算を扱うため、負の数値にも対応します。
指定したレジスタに指定したメモリアドレスを格納する(LAD命令)
LAD命令(Load ADdress命令)は、指定されたアドレスそのものをレジスタにロードする命令です。この命令は、メモリのアドレス自体をレジスタに格納するのが特徴です。データのアドレスを操作する際に使われますが、実際にそのアドレスに格納されている値は取得しません。
- アドレスを直接ロード LAD命令は、指定されたメモリアドレスをレジスタにロードします。データではなく、アドレス自体を処理したい場合に使用されます。
- 例:
LAD GR1, AA ; GR1にアドレスAAをロード
この命令により、GR1レジスタにアドレスAAが直接格納されます【2】。 - 用途 LAD命令は、ポインタ操作やメモリ領域の管理、間接的なメモリ参照が必要な場面で便利です。
主な特徴:
LAD命令は、CASL2や他のアセンブリ言語において、メモリアドレスを効率的に扱うための基本的な命令の1つです。
指定したレジスタに別のレジスタの値や定数を符号なし減算する(SUBL命令)
CASL2のSUBL
命令は、符号なしの論理減算(論理的に値を引く)を行う命令です。SUBA
命令が符号付き減算を行うのに対し、SUBL
は符号を考慮せずに減算します。以下の特徴があります。
- 命令形式:
SUBL gr, adr[, xr]
(メモリからの減算)SUBL gr1, gr2
(レジスタ間の減算)[2]。
- 動作: 指定されたレジスタ内の値から、メモリの値または他のレジスタの値を論理的に減算し、その結果をレジスタに格納します。符号なしの値として扱われるため、負の数にはなりません。
- 用途:
SUBL
は、符号を考慮しない数値処理に使用されます。特に、データが符号なしの整数で表される場面や、単純な論理的な差分を計算する場合に便利です。
指定したレジスタやメモリでAND演算を行う(AND命令)
CASL2のAND
命令は、ビット単位で論理積(AND演算)を行う命令です。この命令は、2つの値の対応するビット同士の論理積を計算し、結果をレジスタに格納します。以下が主な特徴です。
- 命令形式:
AND gr, adr[, xr]
(メモリからの論理積)AND gr1, gr2
(レジスタ同士の論理積)[2]。
- 動作:
- 指定されたレジスタ内の値と、メモリアドレスもしくは他のレジスタの値との論理積を計算します。結果は、指定されたレジスタに保存されます。
- 各ビットに対して、両方が1のときのみ1を返し、それ以外は0になります。
- 用途:
- フラグの設定やビットマスク処理に使用されます。たとえば、特定のビットだけを抽出したいときなどに便利です。
指定したレジスタやメモリでOR演算を行う(OR命令)
CASL2のOR
命令は、ビット単位で論理和(OR演算)を行う命令です。これは2つの値の対応するビット同士を比較し、少なくとも1つが1であれば1を返す論理演算を行います。以下が主な特徴です。
- 命令形式:
OR gr, adr[, xr]
(メモリとのOR演算)OR gr1, gr2
(レジスタ同士のOR演算)
- 動作:
- 指定されたレジスタ内の値と、メモリの値または他のレジスタの値との論理和を計算し、その結果をレジスタに格納します。具体的には、対応するビット同士で少なくとも1つが1であればそのビットは1、それ以外は0になります。
- 用途:
- フラグ設定やビットマスク処理に使用されます。特定のビットを立てたい場合や、複数の条件を満たすかどうかを確認するための処理に役立ちます。
指定したレジスタやメモリでXOR演算を行う(XOR命令)
CASL2のXOR
命令は、ビット単位で排他的論理和(XOR演算)を行う命令です。この演算では、2つのビットが異なる場合にのみ1が返され、同じ場合は0が返されます。以下が主な特徴です。
- 命令形式:
XOR gr, adr[, xr]
(メモリからのXOR演算)XOR gr1, gr2
(レジスタ間のXOR演算)[3]。
- 動作:
- 指定されたレジスタ内の値と、メモリの値または他のレジスタの値のビットごとのXOR演算を行い、その結果をレジスタに格納します。
- 同じレジスタに対してXOR演算を行うと、そのレジスタの値が0になります。これは、レジスタをゼロクリアする便利な手段です[4]。
- 用途:
- 特定のビットを反転させたり、データを暗号化・復号化する際に使用されます。また、レジスタの内容を効率的にクリア(ゼロクリア)する場面でも使われます。
指定したデータ長分の入力データを指定した入力領域に格納する(IN命令)
CASL2のIN
命令は、入力データをメモリに格納するために使用されます。この命令には以下の特徴があります。
- データの入力:
IN
命令は、指定された入力領域に外部からデータを読み込む役割を果たします。通常、コンソールやファイルからデータを取得します。 - レジスタの影響:
IN
命令を実行すると、一般レジスタ(GR)の内容は保持されますが、フラグレジスタ(FR)の内容は不定になります。したがって、IN
命令の前後でFRに依存する処理を行う場合には注意が必要です[2]。 - 使用例: 例えば、
IN 入力領域, データ長
と記述すると、指定したデータ長分の入力データが入力領域に格納されます。
プログラムの開始地点を指定する。(START命令)
CASL2のSTART
命令は、プログラムの開始地点を示すために使用されます。主な役割は、アセンブル時にプログラムの開始アドレスを指定することです。具体的には、以下のような特徴があります。
- プログラムの開始アドレスを指定:
START
命令にはアドレスを指定でき、アセンブラはそのアドレスに基づいてプログラムを配置します。例として、START 100
はプログラムをメモリの100番地から開始させることを意味します。 - プログラムの先頭に配置: 通常、プログラムの最初に
START
命令を記述します。これによって、アセンブラはどこからプログラムをメモリに配置するかを認識します。 - プログラム実行の基準:
START
命令が指定されない場合、アセンブラはデフォルトで開始アドレスを0としてプログラムを配置しますが、明示的に指定することで任意のメモリアドレスからプログラムを実行可能です。
指定したレジスタを算術左シフトする(SLA命令)
CASL2のSLA
命令は、算術左シフト(Arithmetic Left Shift)を行う命令です。ビット列を指定した回数だけ左にシフトし、空いたビットには0が入ります。主な特徴は以下の通りです。
- 命令形式:
SLA gr, n
gr
はシフト対象のレジスタ、n
はシフトするビット数を指定します[2]。
- 動作:
- 指定されたレジスタの内容を
n
ビット分左にシフトし、右側に空いたビットには0が挿入されます。シフトによって符号ビットは保持され、値が大きくなりますが、オーバーフローの可能性があります。 - 算術シフトのため、符号ビット(最上位ビット)は保持され、値の正負は変わりません[2]。
- 指定されたレジスタの内容を
- 用途:
- 乗算を効率的に行いたい場合や、ビット操作で値を大きくしたいときに使用されます。たとえば、
SLA gr, 1
で値を2倍にできます。
- 乗算を効率的に行いたい場合や、ビット操作で値を大きくしたいときに使用されます。たとえば、
指定したレジスタを算術右シフトする(SRA命令)
CASL2のSRA
命令は、算術右シフト(Arithmetic Right Shift)を行う命令です。この命令は、指定されたレジスタ内のデータを右方向にシフトし、符号ビットを保持しつつ、他のビットを指定された回数だけ右に移動させます。以下が主な特徴です。
- 命令形式:
SRA gr, n
gr
はシフト対象のレジスタ、n
はシフトするビット数を指定します[4]。
- 動作:
- レジスタの内容を
n
ビット右にシフトします。シフトされると符号ビット(最上位ビット)は保持され、シフトにより右端に空いたビットには符号ビットと同じ値(0または1)が挿入されます。これにより、符号付き整数の右シフトとして動作し、正負の符号が変わることはありません。
- レジスタの内容を
- 用途:
- 整数の除算を効率的に行う場合や、符号付きの数値をシフトする必要がある場面で使用されます。例えば、
SRA gr, 1
で値を2で割る操作が可能です。
- 整数の除算を効率的に行う場合や、符号付きの数値をシフトする必要がある場面で使用されます。例えば、
指定したレジスタを論理左シフトする(SLL命令)
CASL2のSLL
命令は、論理左シフト(Logical Left Shift)を行う命令です。この命令は、指定されたレジスタ内のビットを左にシフトし、空いたビットに0を挿入します。主な特徴は以下の通りです。
- 命令形式:
SLL gr, n
gr
はシフト対象のレジスタ、n
はシフトするビット数です。
- 動作:
- 指定されたレジスタ内の値を
n
ビット左にシフトします。シフト後、右側に空いたビットには0が入ります。符号ビットも一緒にシフトされるため、符号なしの数値として扱われます。 - 例えば、
SLL gr, 1
を使用すると、そのレジスタ内の数値が2倍になります。
- 指定されたレジスタ内の値を
- 用途:
- ビット操作によって数値を効率的に倍増させたり、ビットマスク操作で使用されます。
指定したレジスタを論理右シフトする(SRL命令)
スタック領域に値を格納する(PUSH命令)
PUSH adr [, x]
SP ← (SP) -L 1
(SP) ← 実効アドレス
- レジスタの値だけをスタックに積む: PUSH 0, GR1
- 指定の値をスタックに積む: PUSH #FF
- ラベルの値をスタックに積む: PUSH DATA
※保存できるレジスタは、GR1 – GR7、GR0は格納できない。
CASL2のPUSH命令は、指定したデータをスタックに格納するために使用されます。以下はPUSH命令の主な特徴です:
- スタック領域へのデータ保存 PUSH命令は、データをスタックに積み上げる命令で、スタックはLIFO(Last In, First Out)方式で管理されます。つまり、後から入れたデータが最初に取り出されます[2]。
- レジスタや定数の退避 PUSH命令は、レジスタの内容や即値(定数)をスタックに保存する際に使用されます。サブルーチン呼び出しや割り込み処理時に、現在の処理状態を保存するのに便利です[6]。
- スタックポインタの自動調整 PUSH命令が実行されると、スタックポインタ(SP)は自動的にデクリメントされ、次の空き領域にデータを格納します。これにより、スタック操作が効率的に行われます[5]。
スタック領域から値を取り出す(POP命令)
スタックからデータを取り出す
POP r
r ← ((SP))
SP ← (SP) +L 1
※格納できるレジスタは、GR0からGR7
CASL2のPOP命令は、スタックに保存されているデータを取り出し、レジスタに格納する命令です。以下がPOP命令の主な特徴です:
- スタックからデータを取り出す POP命令は、スタックに積まれたデータを取り出し、指定されたレジスタに格納します。スタックに最後に保存されたデータが最初に取り出される、LIFO方式です[2]。
- スタックポインタの自動調整 データを取り出した後、スタックポインタ(SP)は自動的にインクリメントされ、次のデータの位置を指します。これにより、スタック操作が自動化され、手動でポインタを操作する必要がありません[1]。
- サブルーチンや割り込み処理の復帰 サブルーチンや割り込みからの復帰時に、保存しておいたレジスタ値や戻りアドレスをスタックから復元する際に使用されます[5]。
指定したサブルーチンを呼び出す(CALL命令)
CALL adr [, x]
SP ← (SP) -L 1,
(SP) ← (PR),
PR r← 実効アドレス
CASL2のCALL命令は、サブルーチン(副プログラム)を呼び出すために使われる命令です。以下が主な特徴です:
- サブルーチンの呼び出し CALL命令は、指定したサブルーチンのアドレスにジャンプし、その処理を開始します。サブルーチンのアドレスはオペランドとして指定されます[4]。
- リターンアドレスの保存 CALL命令を実行すると、現在のプログラムカウンタ(PC)の値、つまりサブルーチンを呼び出した次の命令のアドレスがスタックに保存されます。これにより、サブルーチンが終了した際に元のプログラムに正しく戻ることができます[1]。
- RET命令と連携 サブルーチンの最後には通常、RET命令があり、これによってスタックに保存されたリターンアドレスが取り出され、元のプログラムに戻ります[2]。
GR1~GR7の値をまとめてスタック領域に格納する(RPUSH命令)
CASL2のRPUSH命令は、汎用レジスタ(GR1〜GR7)の内容を一度にスタックに保存するためのマクロ命令です。以下にRPUSH命令の主な特徴を説明します:
- 複数のレジスタを一度にスタックに退避 RPUSH命令は、GR1からGR7までの汎用レジスタの内容を順番にスタックに格納します。これにより、複数のレジスタを一括して保存できるため、サブルーチン呼び出しや割り込み処理時に便利です[1]。
- GR0は含まれない RPUSH命令は、GR1〜GR7のレジスタのみを対象としており、GR0は対象外です。したがって、GR0の内容を保存したい場合は、個別にPUSH命令を使用する必要があります[3]。
- RPOP命令とセットで使用 保存されたレジスタの内容を復元するには、RPOP命令を使用します。RPOP命令は、RPUSHでスタックに保存されたレジスタ値を逆順で取り出し、元のレジスタに戻します[2]。