2017-03-09 23:05 — asano
カテゴリー:
8080からZ80になってありがたいことはいろいろありますが(ハード屋なら5V単一電源になったことが一番ありがたいかも)、IX,IYレジスタが追加されたこともその1つです。でもIX,IY関係の命令って意外と使いにくいのです。
まずHLレジスタと併用できないこと。これはHLレジスタを使う命令にプレフィックスとして0DDH, 0FDHを付けることでHLの部分がそれぞれIX, IYに替わり、(HL)は(IX+d),(IY+d)に替わるようになっているためです。ですから
ADD IX,BC
はできても
ADD IX,HL
はできないのです。
例外的に
LD H,(IX+4)
のようにHまたはLと(IX+d)または(IY+d)の間のLD命令は使えます。
そして上位下位で分割して8ビットレジスタとして使えないこと。インデックスレジスタとしては分割の必要は無いのでそれ自体はかまわないのですが、80系には16ビットレジスタ間の転送が一部の例外(SPへの転送)を除いてできないという特徴があるので、困ったことになります。
例えば
LD HL,BC
という命令はありませんが、
LD H,B
LD L,C
とすることで目的が達せられます。ところがIX,IYではこの手が使えないのです。
LD H,B
命令にプレフィックス0DDHを付けると、IXの上位8ビットにBを転送する命令になります。
これはZ80では未定義命令ですが、少なくともZilog製のZ8400, Sharp製のLH0080, NEC製のμPD780では問題なく実行されます。日立のHD64180ではトラップがかかって実行されないそうです(私は未確認)。それでもこの命令に需要が多いとZilogも認識したのでしょう、Z280の資料では正式な命令として記載されています。
未定義命令を使わない場合、よく使われたのは
PUSH BC
POP IX
とスタックを経由する方法でした。これならHLからIYへの転送等も可能ですが、スタック(メモリ)を経由するのがちょっと気になります。
もっと不便だったのはIX,IYを使っての参照が(IX+d)
の形しかできないこと。(IX+dd)
(16ビットディスプレースメント)とか(IX+A)
(定数ではなくレジスタで)とかが欲しくなることは多いですが、IXを保存しておいて演算するしかないです。
以下は
LD D,(IX+A) ; こんな命令はありません
をどうすれば実現できるか考えたものです。
素直に書けばこんな感じになるでしょうか。
1: 0000 C5 PUSH BC
2: 0001 DDE5 PUSH IX
3: 0003 4F LD C,A
4: 0004 0600 LD B,0
5: 0006 DD09 ADD IX,BC
6: 0008 DD5600 LD D,(IX+0)
7: 000B DDE1 POP IX
8: 000D C1 POP BC
これだとインデックスレジスタとしての機能は使っておらず、単にHLレジスタが2つ(IX,IY)増えただけですよね。Aレジスタは符号無しとして扱われます。符号付にするにはAレジスタの符号によってBレジスタを00Hか0FFHに切り替え(符号拡張)る必要があります。
あるいは自己書き換えを使えばこんな感じで書けます。
1: 0000 320500 LD (L0+2),A
2: 0003 DD5600 L0: LD D,(IX+0)
2行目の命令のディスプレースメント部分にAの値を実行時に書き込むわけです。この場合はAレジスタは符号付として扱われます。もちろんROM上では実行できません。
コメントを追加