本当に初心者の人に捧げるコンピューター入門


補足 その5−B

Z−80の命令の簡単な解説(1)

 以下はZ−80にはどんな機能があるかということの解説です。
 これを見てもらえば、本物の機械語でも偽機械語に比べて本質的に優れているものではないということがわかると思います。

データ転送命令



 レジスタ←メモリー、レジスタ←レジスタ、メモリー←レジスタ、レジスタ←値、メモリー←値といった間でデータを転送する命令です。
 同じLD命令でも組み合わせごとに違った機械語が割り当てられています。

命令意味
LD データ転送命令。
LDI,LDIR 後方に向かったブロック転送処理*をします。
LDD,LDDR 前方に向かったブロック転送処理をします。

 LD命令はほとんどのレジスタ・メモリーの組み合わせが可能です。例えばAレジスタにBレジスタの値をを入れろという命令は

  LD  A  B

とアセンブリ表記して、機械語は78hです(AレジスタもBレジスタも場所があらかじめ分かっているので、引数は不要です)
 しかしほとんどとはいっても全てではありません。例えばIレジスタに値を転送したい場合は必ずAレジスタからでなければならないという決まりがあります(CPU設計上そうなっているのです)
 今回の説明ではその辺の細かいところは書いてもうっとうしくなるだけなので割愛します。以下の命令の説明もそのつもりで読んでください。

ブロック処理

 こういう〜I,〜D,〜IR,〜DRとかいう名前の命令は以下にも出てきますが、ブロック処理命令といって一定範囲のメモリーに同じ処理をしたいときなどに大変便利です。

 LDI命令は、あらかじめHLレジスタに転送元のメモリーのアドレス、DEレジスタに転送先のアドレス、BCレジスタに適当な数をセットしておくと、HLレジスタの指しているアドレスからDEレジスタの指しているアドレスにデータをコピーした後に、HLレジスタとDEレジスタのの値を+1して、BCレジスタの値を−1してくれます。
 LDIR命令はBCレジスタの値が0になるまで上の動作を繰り返します。
 あるメモリーのある領域から別な領域にまとめてデータをコピーしたい時に大変便利な命令です。

 LDD命令はLDI命令とほぼ同じですが、HLレジスタとDEレジスタの値が−1されるところが違います。


演算命令



 足し算・引き算・値の比較などを行う命令です。
 この命令を行うためには8ビット演算の場合は必ずAレジスタに、16ビット演算の場合はHL,IX,IYレジスタのどれかに入れておかなければなりません。

命令 意味
ADD 加算。
ADC キャリーつき加算(加算するときにキャリーフラグの値も一緒に加算される)繰り上がりが発生する複数のバイトからなる数を計算するとき使う。
SUB 減算。
SBC キャリーつき減算(減算するときにキャリーフラグの値も一緒に減算される)繰り下がりが発生する複数のバイトからなる数を計算するとき使う。
INC あるレジスタの値に1を足す。別にADDで1を足しても同じようだが、こちらの方が高速に計算できる
DEC あるレジスタの値から1を引く。INC同様にこちらの方が高速に計算できる
CP 値の比較をする。
CPI,CPIR 後方へのブロックサーチをする。ブロック転送のように一定のメモリー範囲を一気に調べたいとき便利。
CPD,CPDR 前方へのブロックサーチをする。
NEG 補数をとる*
CCF キャリーフラグの反転。
SCF キャリーフラグのセット。
DAA 10進補正**

補数

 補数をとるとは、値の二進数の各桁の1,0を反対にして1を足した値を得ることです。例えば 00000001 という値の補数は 11111111 です。これに何の意味があるかというと、実はその値の+−の符号を反対にするのと同じなのです。どうしてかって?コンピューター内部で負の数はどうやって表現されていたでしょう
 Xと−Xの値には実はこんな関係があったんです。

** 10進補正

 これは2進化10進数というのを扱うとき使います。
 コンピューターの内部ではすべて2進法で表現されているため、例えば1/5という値を表現すると内部的には無限小数になってしまい、正確な値にはならないことを前に説明しました。
 しかしお金の計算などをするときにはこれでは困ります。そこで考えられたのが2進化10進数です。
 これは一口でいえば、16進数で書かれたは10hという値を、10進数の10であると見なして計算できるようにしてしまおうというものです。

 例えば16進数で書かれた以下の足し算は正しいですね。

 12h+23h=35h

 ところが繰り上がりさえなければ、hをはずして10進数と見なしても同じ結果になります。

 12+23=35

 でも実際には繰り上がりがあって下のようなことになってしまいます。

 12h+29h=3Bh
 12+29=41

 そこで例えば3Bhという値が来たら41hになるように補正する命令を作っておけば、あたかも16進数で10進数の計算ができるように見えるわけです。


シフト・ローテート命令



 これはレジスタの値のビットを回転させたりシフトさせる命令です。

命令 意味
SLA 左シフト
SRA 右シフト(7ビット目=7ビット目)
SRL 右シフト(7ビット目=0)
RL,RLA 左ローテート(A付きはAレジスタ専用で高速)
RLC,RLCA キャリーフラグも含めて左ローテート(A付きはAレジスタ専用で高速)
RR,RRA 右ローテート(A付きはAレジスタ専用で高速)
RRC,RRCA キャリーフラグも含めて右ローテート(A付きはAレジスタ専用で高速)
RLD 2進化10進数用左ローテート
RRD 2進化10進数用右ローテート

 といっても何のことだか分からないでしょうから例を挙げてみると

左シフト   左ローテート 右シフト   右ローテート
処理前 11001101 11001101 11001101 11001101
処理後 10011010 10011011 01100110 11100110

 よく見れば分かるとおりシフトでは数字の位置が一個ずれており、ローテートではずれて出ていった数字が反対側から回り込んできています。でもこんなことに何の意味があるのでしょう?

 Z−80の演算命令には足し算と引き算しかありません。しかし実用上かけ算などができなければ電卓以下です。しかしそういう命令がない以上、結局かけ算をするプログラムを作らなければなりませんが、ちょっと考えると大変そうです。
 でも昔小学校でかけ算を習ったとき、下のような問題なら楽だったでしょう?。

     12345
    × 1011  ←掛ける数が全部1と0でできている
  ------------------
     12345
    12345      ←1の桁だったら単にずらしただけになっている!
   00000        ←0だったら0
  12345
  ------------------
 前にコンピューターは2進法しか分からないと書きました。2進法にははもちろん1と0しかありません!というわけで数字をずらすという命令があればかけ算がとっても楽になるのです!


論理演算命令



偽機械語にもあった論理演算命令です

命令 意味
CPL AレジスタのNOTをとる
AND Aレジスタと他のレジスタのANDをとる
OR Aレジスタと他のレジスタのORをとる
XOR Aレジスタと他のレジスタのXORをとる*

 ところで偽機械語では1と0のことしか書いてませんでしたが、レジスタは最低でも8ビットあるので他の数も書くことができます。

 それでは二つのレジスタに1,0以外の値が入っていたら一体どうなるのでしょう?
 下にいくつか例を挙げましょう。

 100 AND 200 =64
 170 AND 85  =0
 255 AND 100 =100
 なんだか謎めいていますが、種明かしは簡単です。機械語の論理演算命令は、2進法で表した数の対応する各桁ごとに論理演算(ANDやORなど)するのです。最初の例の説明をすると、

 100=0100100
 200=1001000
  ↓
  64=0000000
というように各桁ごとにANDを行っており、二つの数で同じ桁に1があるところ(太字)だけ1になって、それ以外の桁は0になってしまうので、こんな答えが返ってきたのでした。
 OR命令はANDの代わりに各ビットごとのORをとります。
 CPL命令は各ビットのNOT、すなわち反転をします。

XOR命令

 ところでXORというの聞いたことがありますか?これは各ビットごとに以下のような演算をします。

 0 XOR 0 → 0
 1 XOR 0 → 1
 0 XOR 1 → 1
 1 XOR 1 → 0   ←ここだけがORと違う
 つまり二つの項が等しければ0、違っていれば1と考えればいいでしょう。それだけならなんてことはありませんが、この命令には以下のような非常に便利な特徴があるのです。

 A XOR B = C になるとすると C XOR B = A になる

 つまりAとBのXOR演算をした結果に対して、もう一度BでXOR演算をすると元と同じAになるのです。
 例を挙げると

123(01111011)XOR 58(00111010)= 65(01000001)
 65(01000001)XOR 58(00111010)=123(01111011)

 だからどうしたって?
 オトナなら
この例で分かってもらえるはずです・・・


ビット演算命令



 この命令はレジスタ内部の数の各ビット単位でいろいろな処理をしたいときに使います。
 
命令 意味
BIT ビットテスト。値の各ビットが1かどうかチェックする。
SET ビットセット。指定したビットを1にする。
RES ビットリセット。指定したビットを0にする。

 特に昔はメモリーが高価だったので、1ビットで済むような情報(例えばBGMのON/OFFとか)を保存しておくの1バイトも使うのは悪徳とされていました。2進法の1桁をこういう情報の保管に使えれば、1バイトに8つの情報を詰め込むことができるわけです。


ジャンプ命令



 偽機械語と同様にプログラムの実行順序を変える命令です。

命令 意味
JP 絶対アドレスにジャンプする
JR 相対アドレス(現在の場所から何番地後とかいうように)ジャンプする。
DJNZ 一定範囲置きにジャンプ

ジャンプ命令には以下のように条件を付けることもできます

Z ゼロフラグが1だった場合
NZ ゼロフラグが0だった場合
C キャリーフラグが1だった場合
NC キャリーフラグが0だった場合
P 符号フラグが0だった場合(結果が+か0だった場合)
M 符号フラグが1だった場合(結果が−だった場合)
PE パリティーフラグが0だった場合
PO パリティーフラグが1だった場合


 長くなったので続きは次のページです!


前へ 目次へ 次へ