LD AC, arg ←命令書式 nbyte 2 ←nbyte(バイト数指定) opcode 10001100 ←opcode(命令コード) 0: MAR <- PC, PC <- inc ←実行内容 1: MDR <- mem 2: IR <- MDR 3: MAR <- PC, PC <- inc 4: MDR <- mem 5: AC <- MDR JMP label alias JMP (arg) ←alias(別名指定)命令定義ブロックの1行目は命令書式である。命令書式(1行目)は行の先頭から書く。 2行目以降は、先頭に1個以上のタブまたは半角空白を置く。命令書式の記述を1行目とする以外は、2行目以降の記述順序は自由である。
'arg'と'label'は特別な語であり、プログラム中の命令の対応する語が即値あるいはラベルである場合に命令パターンがマッチすることを意味する。詳細は「アセンブラの動作」の項を参照のこと。
例えば、上の例では、命令'JMP label'は命令'JMP (arg)'の別名であると 定義している。aliasによる別名定義よりも前に、別名の元となる命令 (この場合は'JMP (arg)')の命令定義がなされていなければならない。
実行条件: マイクロ操作列
状態フラグ条件がない場合は、実行条件は実行タイミングを表す整数のみと
なる。実行タイミングと状態フラグ条件の両方がある場合は、実行タイミング
を表す整数の直後に'&'をおき、状態フラグ名を連結する。
なお、実行タイミングがなく、状態フラグ条件のみの実行条件は禁止する。
例えば最初のタイミング0で実行するマイクロ操作列の場合は、
0: マイクロ操作列となる。
4&C: マイクロ操作列となる。
4&Z&NC: マイクロ操作列となる。
なお、以下のように実行タイミングが同じものがある場合は、該当するタイミングにおいてすべてのマイクロ操作が実行される。
5: マイクロ操作列1 5&Z: マイクロ操作列2すなわち、タイミング5において状態フラグZ=1ならばマイクロ操作列1とマイクロ操作列2の両方が実行される。タイミング5において状態フラグZ=0ならばマイクロ操作列1だけが実行される。
マイクロ操作あるいは
マイクロ操作, マイクロ操作, ...., マイクロ操作となる。
ELC-1における制約
ELC-1では、各命令実行のタイミング0~2は命令フェッチ(メモリからの命令のオペコードの読み出し)である。命令を読み出して命令レジスタIRに代入するまでは、それがどのような命令であるかは不明である。したがって、タイミング0~2では全ての命令において命令フェッチのために共通のマイクロ操作を実行しなければならない。 ELC-1の命令フェッチをマイクロ操作によって表すと以下の通りである。 0: MAR <- PC, PC <- inc 1: MDR <- mem 2: IR <- MDRすべての命令定義において、タイミング0~2のマイクロ操作をこのようにすること。 |
データ転送先 <- データ転送元と記述する。データ転送先には PC, B, X, MAR, MDR, MDRH, IR、 データ転送元には、レジスタPC, AC, B, WA, X, MAR, MDR, MDRWまたはmemが指定できる。 memは、レジスタMARの内容をアドレスとする位置のメモリ内容を表す。
なお、ACとWAをデータ転送先とする場合については、「ALUを用いた演算」(無処理)の項を参照のこと。
例 |
---|
MDR <- AC
アキュムレータACの値をレジスタMDRに転送する
|
MAR <- PC
レジスタPCの値をレジスタMARに転送する
|
MDRH <- MDR
レジスタMDRの値をレジスタMDRHに転送する
|
X <- MDRW
レジスタMDRWの値をレジスタXに転送する
|
MDR <- mem
レジスタMARをアドレスとするメモリ位置の内容をレジスタ
MDRに転送する
|
ELC-1における制約
ELC-1では、メモリの内容をレジスタMDR以外のレジスタに直接転送できない。 これは、メモリのデータ出力がレジスタMDRの入力に接続されているためである。 データ転送マイクロ操作の文法としては、memをMDR以外のレジスタに転送するように記述することは可能であるが、ELC-1の仕様としてメモリからのデータ転送は、転送先がMDRである MDR <- memのみが使用でき、これ以外は禁止する。 |
ELC-1における制約
ELC-1では、レジスタMDRHの転送元としてレジスタMDRのみが指定できる。 |
a: データ転送先16ビットレジスタ <-H データ転送元8ビットレジスタ b: データ転送先16ビットレジスタ <-L データ転送元8ビットレジスタ c: データ転送先8ビットレジスタ <-H データ転送元16ビットレジスタ d: データ転送先8ビットレジスタ <-L データ転送元16ビットレジスタ e: データ転送先16ビットレジスタ <- データ転送元8ビットレジスタ f: データ転送先8ビットレジスタ <- データ転送元16ビットレジスタ記述aは、転送元の8ビットデータを転送先16ビットレジスタの上位8ビットに転送する。
例 |
---|
MDR <- X
レジスタXの下位8ビットをレジスタMDRに転送する
|
MDR <-L WA
レジスタWAの下位8ビットをレジスタMDRに転送する(上と同じ)
|
X <-H AC
アキュムレータACの値をレジスタXの上位8ビットに転送する
|
ELC-1における制約
ELC-1では、レジスタMAR, PCに8ビットデータを転送することはできない。 |
状態フラグ <- 1(0)と記述する。状態フラグとしてS, Z, C, Hが指定できる。
例 |
---|
C <- 1
状態フラグC(carry)を1に設定する
|
H <- 0
状態フラグH(halt)を0に設定する
|
例 |
---|
PC <- inc
レジスタPCの値をインクリメントする
|
X <- dec
レジスタXの値をデクリメントする
|
なお、ELC-1では、レジスタPCにはインクリメント機能、レジスタ WA、X、MAR、Bにはインクリメント機能とデクリメント機能がある。
アキュムレータACに対して同様にインクリメントとデクリメントを指令することができるが、ACの場合はレジスタ(アキュムレータ)の機能ではなく、ALUを用いてインクリメントとデクリメントを行う。
詳細は、ALUを用いた演算の項を参照のこと。
レジスタWAのインクリメント/デクリメントはALUを使用せずに行うので、ALUを用いた(ACに関する)演算とレジスタWAのインクリメント/デクリメントを同時に行うことができる。 なお、WAのインクリメント/デクリメントはALUを使用しないため、フラグが変化しないので注意のこと。 |
タイミングレジスタの値をマイクロ操作によって強制的に変更することで、命令実行手順を変更することができる。タイミングレジスタの値の変更は
-> 変更値である。
JC arg nbyte 2 opcode 10000100 0: MAR <- PC, PC <- inc 1: MDR <- mem 2: IR <- MDR 3&NC: -> 0 ←条件依存タイミングレジスタ変更 3: MAR <- PC, PC <- inc 4: MDR <- mem 5: PC <- MDRこれは状態フラグCの値が1ならば、分岐(プログラムカウンタPCの値の変更)を行う命令である。実行タイミング3では、PCの値をMARに転送し、この命令のオペコードの直後にある分岐先アドレスをメモリから読み出す準備をしている。同時に、実行条件3&NCによって状態フラグCの値を検査し、C=0ならば次の実行タイミングを0にする(3&NC: -> 0)。 これにより、この命令の実行を中断し、直後の命令の命令フェッチへと進む。 すなわち、C=0ならば分岐は行わない。
C=1ならば条件3&NCは偽なので、タイミングレジスタへの0の代入は行われず、タイミングレジスタの次の値は4となる。そして、4以降では分岐先アドレスを実際にメモリから読み出し、PCへ代入することで分岐を行う。すなわち、C=1ならば分岐が行われる。
なお、現在の実行タイミングkにおける'-> (k+1)'、および最後の実行タイミングにおける'-> 0'は省略できる。
WR = 1によって行う。メモリからデータを読み出す場合には'WR = 0'とする必要があるが、'WR = 0'は省略できる。
なお、ALUへ入力するデータとALU処理結果は、データのビット数とALU処理内容に依存して取り扱われる。詳細は「マイクロプロセッサELC-1の構成要素」(ALU)を参照のこと。
例 |
---|
AC <- AC + X
アキュムレータACにレジスタXの値を加える
|
WA <- WA + MDR
レジスタWAにレジスタMDRの値を加える
|
AC <- AC + AC
アキュムレータACの値を2倍する
|
現在の状態フラグC(桁上げ, carry)の値も加える場合は、 演算子として'+c'を用いる。
例 |
---|
AC <- AC +c MDR
アキュムレータACにレジスタMDRの値と状態フラグCの値を加える
|
すなわち、C=0ならばAC+MDR、C=1ならばAC+MDR+1がACに代入される。
例 |
---|
AC <- AC - X
アキュムレータACからレジスタXの値を引く
|
WA <- WA - MDRW
レジスタWAからレジスタMDRWの値を引く
|
AC <- AC - AC
アキュムレータACの値を0にする
|
現在の状態フラグCの値も引く場合は、演算子として'-c'を用いる。
この場合の状態フラグCの意味は桁借り(borrow)となる。
例 |
---|
AC <- AC -c MDR
アキュムレータACからレジスタMDRの値と状態フラグCの値を引く
|
すなわち、C=0ならばAC-MDR、C=1ならば AC-MDR-1がACに代入される。
入力1 | 入力2 | 出力 |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
例 |
---|
AC <- AC & B
アキュムレータACとレジスタBの値の論理積を求める
|
WA <- WA & MDR
レジスタWAとレジスタMDRの値の論理積を求める(この場合、MDRの上位に8ビットの0が補われてから論理積を求める結果、WAの上位8ビットは0になる)
|
入力1 | 入力2 | 出力 |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
例 |
---|
AC <- AC | X
アキュムレータACとレジスタXの値の論理和を求める
WA <- WA | MDRW
レジスタWAとレジスタMDRWの値の論理和を求める
|
入力1 | 入力2 | 出力 |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
例 |
---|
AC <- AC ^ X
アキュムレータACとレジスタXの値の排他的論理和を求める
|
WA <- WA ^ MDR
レジスタWAとレジスタMDRの値の排他的論理和を求める
(この場合、MDRの上位に8ビットの0が補われてから排他的論理和を求める結果、WAの上位8ビットは変化しない)
|
AC <- AC ^ AC
アキュムレータACの値を0にする
|
演算子 | 処理名 | 処理内容 |
<< | 論理左シフト | データを左に1ビットシフトする。 シフト後のデータのLSB(Least Significant Bit, 最下位ビット)は、0とする。 シフト前のデータのMSB(Most Significant Bit, 最上位ビット)を状態フラグCに代入する。 |
<<c | 桁上げつき 論理左シフト |
データを左に1ビットシフトする。 シフト後のデータのLSBには、状態フラグCの値を代入する。 シフト前のデータのMSBを状態フラグCに代入する。 |
>> | 論理右シフト | データを右に1ビットシフトする。 シフト後のデータのMSBは、0とする。 シフト前のデータのLSBを状態フラグCに代入する。 |
>>c | 桁上げつき 論理右シフト |
データを右に1ビットシフトする。 シフト後のデータのMSBには、状態フラグCの値を代入する。 シフト前のデータのLSBを状態フラグCに代入する。 |
>>a | 算術右シフト | データを右に1ビットシフトする。 シフト後のデータのMSBには、シフト前のデータのMSBの値を代入する。 シフト前のデータのLSBを状態フラグCに代入する。 |
シフト処理は、アキュムレータACまたはWAの内容をビットパターンとして左右に1ビットだけずらすと解釈する他に、ACまたはWAの内容が数であると考えれば右シフトは2分の1、左シフトは2倍にする処理であると解釈することもできる。
算術右シフトは、アキュムレータACまたはWAのMSBの値が変化しない右シフトである。
符号つき数ではMSBを符号ビットとみなし、数が非負の場合はMSBは0、負の場合はMSBは1である。正の数を2分の1にした結果は
正であり、負の数を2分の1にした結果は負であるから、符号ビットの値、すなわちMSBの値は不変とすべきである。よって、MSBの値を保存する算術右シフトによって、ACまたはWAの内容を符号つき数として正しく2分の1にすることができる。
シフト演算子とシフト処理内容の対応を図3に示す。
図3. シフト演算子と処理内容 |
例 |
---|
AC <- AC << 1
アキュムレータACを論理左シフトする
|
WA <- WA >>c 1
レジスタWAを桁上げつき論理右シフトする
|
AC <- AC >>a 1
アキュムレータACの内容を1/2倍する
|
注意
演算子の右の被演算項の1はシフト数が1ビットであることを意味するが、形式的なものである。 ELC-1では2以上の値を指定しても意味はなく、シフトは常に1ビットである。 |
例 |
---|
AC <- inc
アキュムレータACの内容を1だけ増加する
|
AC <- dec
アキュムレータACの内容を1だけ減少する
|
例 |
---|
AC <- cmp
アキュムレータACの各ビットを反転する
|
WA <- cmp
レジスタWAの各ビットを反転する
|
例 |
---|
AC <- neg
アキュムレータACの値の符号を反転する
|
WA <- neg
レジスタWAの値の符号を反転する
|
例 |
---|
AC <- MDR
アキュムレータACにレジスタMDRの値を転送する
|
WA <- X
レジスタWAにレジスタXの値を転送する
|
演算の種類 | S | Z | C |
加算 減算 |
↑↓ | ↑↓ | ↑↓ |
AND(論理積) OR(論理和) XOR(排他的論理和) |
↑↓ | ↑↓ | ↑↓ |
シフト | ↑↓ | ↑↓ | ↑↓ |
インクリメント デクリメント |
↑↓ | ↑↓ | - |
ビット反転 | ↑↓ | ↑↓ | - |
符号反転 | ↑↓ | ↑↓ | - |
無処理 | - | - | - |
例 |
---|
AC - MDR
アキュムレータACとレジスタMDRの値を比較し、その結果に応じて状態フラグを設定する |
AC & MDR
アキュムレータACとレジスタMDRの値の論理積を求めることで、AC内の特定のビットが1であるか0であるかを調べる
|
AC - MDRでは、もしもMDRの値が10のとき、ACが10以上ならば引き算の結果は正または0なので、状態フラグSは0になる。
さらにACが10よりも大きければ、状態フラグZも0になる。
ACが10未満ならば引き算の結果は負なので、Sは1になる。
よって、ACの値と比較対象(この例ではMDR)との大小関係により、状態フラグは表2のように設定される。表2では、'・'は0または1のいずれかになることを表している。
大小関係 | S | Z | C |
AC>比較対象 | 0 | 0 | 0 |
AC≧比較対象 | 0 | ・ | 0 |
AC=比較対象 | 0 | 1 | 0 |
AC≦比較対象 | ・ | ・ | ・ |
AC<比較対象 | 1 | 0 | 1 |
AC≠比較対象 | ・ | 0 | ・ |
AC & MDRでは、もしもMDRの値が1のとき、ACのLSB(Least Significant Bit, 最下位ビット)が1ならば論理積は1、LSBが0ならば論理積は0となる。
よってAC & MDRの後で状態フラグZの値が0ならばACのLSBは1、Zの値が1ならばACのLSBは0であることが分かる。
MDRの値を2とすればACの最下位から2ビット目、MDRの値を8とすればACの最下位から4ビット目の検査ができる。
また、MDRの値を6とすればACの最下位から2ビット目と最下位から3ビット目の少なくともいずれかが1である、あるいは両方とも0である、のどちらであるかを検査することができる。
例えば、命令フェッチのため実行タイミング0で行うマイクロ操作は
0: MAR <- PC, PC <- incと記述されている。これは、現在のプログラムカウンタPCの値をレジスタMARに転送し、PCをインクリメントするという2つのマイクロ操作からなる。PCにインクリメント後の新しい値が設定されるのは、実行タイミング0と実行タイミング1の境界のクロック信号立上り時点であり、それまではPCの値に変化はない。したがって以下のように記述しても、MARとPCに設定される値は上の記述の場合と同じである。
0: PC <- inc, MAR <- PC
さらに、他のレジスタを使わずにレジスタWAとレジスタXの内容を入れ替えることもできる。これは、以下のように記述すればよい(実行タイミング5において行う場合)。
5: WA <- X, X <- WA
LD AC, (arg) nbyte 3 opcode 10010010 0: MAR <- PC, PC <- inc 1: MDR <- mem 2: IR <- MDR 3: MAR <- PC, PC <- inc 4: MDR <- mem, MAR <- PC, PC <- inc 5: MDRH <- MDR, MDR <- mem 6: MAR <- MDRW 7: MDR <- mem 8: AC <- MDRこれは、1バイトの命令コードと2バイトのオペランドからなる3バイト長の命令であり、オペランドをメモリアドレスとして用いてメモリからデータを読み出し、ACに保存する。
現在のPCの値が125(10進数)であり、メモリの内容が図4(a)のようになっているとき、命令定義にしたがってプロセッサが動作するときのレジスタの値の変化の様子を図4(b)に示す。
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(a) | (b) |
オペランドはメモリアドレス126, 127に格納されており、命令実行クロック4で最初の1バイト(8ビット), 命令実行クロック5で次の1バイト(8ビット)を順に読み出す。この命令では、オペランドは16ビットのメモリアドレスとして利用するので、これら2バイトを連結して16ビットのオペランドデータ(メモリアドレス)とする必要がある。
2つのバイトデータを連結して16ビットデータとするにはMDRWを利用する。すなわち、オペランドの最初の1バイト(8ビット)をMDRHに転送し、オペランドの次の1バイト(8ビット)がMDRに入った時点でMDRWが16ビットのオペランドとなる。
上の例ではオペランドの2つのバイトデータの値は$01, $B7(いずれも16進数)であり、これらを連結した16ビットの値は$01B7(16進数)となる。$01がMDRHに、$B7がMDRに入ったときMDRWが16ビットの$01B7となる。
MDRWの16ビット値をMARに転送してメモリアドレスとして使用してメモリからデータを読み出し、最後にACに転送する。