S−OS講座「Z80:レジスタ間接アドレッシング」  長いブランクが空いてしまい、ほとんど連載の意味がなくなってしまいましたが、 みなさまお元気でしたでしょうか?私にとってこの1年は、悩み多き年でありました。 おかげで「S−OS通信」の発行も遅れに遅れ、とうとう1年たってしまいました。 ごめんなさい。  さて、前回(去年の話ね)は「Aレジスタ(及びCフラグ)を使った計算」の話で した。忘れた人、Vol.2を読み返してください。 前回では、Aレジスタの内容をメモリに書き出すのに LD  (アドレス),A を使用していましたが、この命令は3バイトなので、繰返し使用するとメモリを食っ てしまいます。このように、メモリのある番地(アドレス)を指定するのに、直接ア ドレスをオペランドとして書く方式を「直接アドレッシング」といいます。 これに対して、アクセスするアドレスをZ80のレジスタに書いておいて、命令で はそのレジスタの名前を指定する、 「レジスタ間接アドレッシング」 という方法があります。 Z80で、アドレスを指定するレジスタとして最も多く使用されるのが、 HLレジスタ です。これは16ビット(0000H〜FFFFH)の大きさを持ち、上位8ビットのHレジスタ 下位8ビットのLレジスタとして、分割して使用することも可能です。 例として、HLレジスタ間接による3バイト書き込みのプログラムを見てみましょ う。 【プログラム】8010H〜8012H番地に 12H,34H,56H を格納する。 ラベル ニモニック コメント --------+-------+---------------+------------------------------- ORG 8000H ; 8000Hから始めよ LD HL,8010H ; HLレジに 8010Hを入れる LD A,12H ; Aレジに12Hを入れる LD (HL),A ; HLの指すアドレスにAの中身を格納 INC HL ; HLレジを+1する LD A,34H ; Aレジに34Hを入れる LD (HL),A ; HLの指すアドレスにAの中身を格納 INC HL ; HLレジを+1する LD A,56H ; Aレジに56Hを入れる LD (HL),A ; HLの指すアドレスにAの中身を格納 RET ; 終わり ここで「INC  HL」というのは、HLレジスタの内容を1つ増やす命令です。 逆に、1つ減らす命令は「DEC  HL」です。 「LD  (HL),A」は1バイト長の命令ですから、3バイト以上の書き込みな らば、直接アドレスよりHL間接アドレスの方がプログラムが短かくなります。  アセンブル、実行してみると、8010H〜にちゃんと格納されていますね。 A>A A>J8000 A>D8000 :8000 21 10 80 .. .. :8008 .. .. .. .. .. :8010 12 34 56 .. .. ... Z80にはこの他にも、B/C/D/Eの汎用レジスタ(注1)があり、それぞれ ペアにして、BCレジスタ、DEレジスタとして使用することができます。ただし、 レジスタ間接アドレッシングでBC/DEレジスタを用いる場合は、HLレジスタに 比べると、次のような制限があります。例えば LD (HL),B や ADD A,(HL) という命令はありますが、 LD (DE),B や ADD A,(BC) という命令はありません(HLレジスタ間接の場合、対象レジスタは何でも良いが、 BC/DEレジスタ間接の場合は、対象レジスタはAレジでなければならない)。  HLレジスタの他に、BC/DEレジスタを使用すると、次の2つの例のようなプ ログラムが書けるようになります。 【例1】8020H〜8022H番地の内容を、8028H〜802AH番地へ複写する。 ラベル ニモニック コメント --------+-------+---------------+------------------------------- ORG 8000H ; 8000H番地より始めよ LD HL,8020H ; 転送元(ソース) LD DE,8028H ; 転送先(ディスティネーション) LD A,(HL) ; A←(HL) INC HL ; HL←HL+1 LD (DE),A ; (DE)←A INC DE ; DE←DE+1 LD A,(HL) INC HL LD (DE),A INC DE LD A,(HL) LD (DE),A RET ; S-OSに戻る アセンブル、実行してみましょう。下のようになりましたか? A>A A>D8000 :8000 21 20 80 .. .. ... :8020 12 34 56 .. .. ←自分で書き換えてを押す :8028 ?? ?? ?? .. .. ... A>J8000 A>D8000 ... :8020 12 34 56 .. .. :8028 12 34 56 .. .. ←内容が転送されている (練習問題)8020H〜8023Hの内容を、8028H〜802AHに逆順に、つまり (8020H)→(802AH) (8021H)→(8029H) (8022H)→(8028H) とするプログラムを考えてください。 【例2】8020H〜8022H番地の内容と8024H〜8026H番地の内容の和を求め、結果を 8028H〜802AH番地に格納する。ただし数値は、下位・中位・上位の順。 ラベル ニモニック コメント --------+-------+---------------+------------------------------- ORG 8000H LD BC,8020H ; 「たす数1」のアドレス LD HL,8024H ; 「 〃 2」のアドレス LD DE,8028H ; 「計算結果」のアドレス。 LD A,(BC) ; A←(BC) INC BC ; BC←BC+1 ADD A,(HL) ; A←A+(HL) *1 INC HL ; HL←HL+1 LD (DE),A ; (DE)←A INC DE ; DE←DE+1 LD A,(BC) INC BC ADC A,(HL) ; A←A+(HL)+Cフラグ *2 INC HL LD (DE),A INC DE LD A,(BC) ADC A,(HL) LD (DE),A RET  アセンブラモードで、次のように実行してみましょう。ちゃんと足し算できました か? A>A A>D8000 :8000 01 20 80 .. .. .. ... :8020 56 34 12 00 BC 9A 78 00 ←自分で入れる :8028 ?? ?? ?? .. .. .. ... A>J8000 A>D8000 ... :8028 12 CF 8A .. .. ←答えが入っている ...  ここで1つ疑問が出てきます。ADC命令を使って2バイト以上の足し算を行なう 場合、Cフラグの内容を前のADD命令の桁上がりの有無として使用しますが、プロ グラム中(*1)のADD命令と、(*2)のADC命令の間に「INC命令」が入っていま すね。INC命令はレジスタに1を「足す」命令ですが、+1して桁あふれしたら、 Cフラグの内容はどうなるんでしょうか? 桁あふれしないとしても、(*1)のADD 命令でもし桁上がりが生じていた場合、Cフラグはリセットされてしまわないでしょ うか?  結論を申しますと、 INC命令では、Cフラグの変化はない ということになります。つまり、FFFFHをINC命令で+1すると、Cフラグは そのままで、レジスタの内容だけが0000Hとなります。INC命令で桁あふれし たかどうかを調べるには、レジスタの内容が0000Hかどうかを見ればよいという ことです。  ちょっと長くなってしまったので、ジャンプ命令については、次回取り上げること にします。それでは、また。 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− (注1)他にも「裏レジスタ」というものもあるが、ここでは割愛する。  本コーナーや、S−OSシステムに関するご質問は、同封はがきまたは封書で事務 局まで。また「S−OSネット大阪」(06)969-8459でも受け付けております。 (EOF)