零壱症候群1より
阿閉雅宏の Z-80まにあくす Stage.03
解説:杉之原名人
 コンピュータを扱う者は必ずといってよいほど、一度はマシン語でプログラムを作ってみたいという願望にかられるものです。マシン語入力の際に起こるバグ、入力ミスなどの探し方はこの次にして、今回はメモリを節約するための、要するに大部分打ち込んだのに少しだけメモリが足りないというときのためのテクニックを報告します。
1:ビット処理応用編
 レジスタの複数ビットを調べるのは大変です。それを一度に調べられるようにしたのが以下のプログラムです。
 例えばCレジスタ
PUSH BC
POP AF

として、後は条件ジャンプによってフラグ変化を調べるのみ。
 次はBレジスタ

PUSH BC
INC SP
POP AF
DEC SP

とすれば調べられます。

2:条件分岐編
 例えば、条件プログラム(IF文とおなじ)の際は、A=N1でB=D,A=N2でB=E,それ以外はB=H(Aは破壊しても良い)というプログラムを考えた場合、以下のように実装することができます。
CP N1
JR Z ,P1
CP N2
JR Z ,P2
LD B , H
DEFB 3E(H) LD A,imm命令のオペコード
P1 LD B , D
DEFB 3E(H) LD A,imm命令のオペコード
P2 LD B , E
※DEFBを利用してLD A,imm命令のオペコードを置くことにより、次の1バイト命令をオペランドとして認識するようにしている。これによってAレジスタは破壊されるが、JR命令で続く命令をスキップさせる必要がなくなる。JR命令は2バイトで12クロックを要するので、サイズ的にも速度的にも有利と考えられる。
3:ブロック転送及びDJNZ編
 ブロック転送及びDJNZでのループ後は、BCレジスタの値がそれぞれ0であることを利用します。
 LDIR,LDDRの時
      BC=0
 OTIR,OTDR,INIR,INDR,DJNZの時
      B=0
ループを抜け出す時は必ずこうなっています。
4:キャリーフラグ編
 常にCyフラグの値を記憶する。(SBC HL,rr'etc.の為)
 論理演算後は、Cyフラグが0になることを利用する。
5:条件CALL編
 一部しか違わないプログラムは、CALL条件、nn'を利用する。
 サブルーチン的使用をする。(フラグ処理が必要)
PUSH AF
CALL NC, 処理-1用
POP AF
CALL C, 処理-2用
6:フラグ処理編
使い道がありそうなのは、
PUSH AF
POP rr'
 その後は、BIT命令で処理。これにより、スタックとフラグ変化を気にかけずにフラグによる処理ができる。
7:解析されにくいプログラム用
PUSHされたデーターをサブルーチンとして使う。
LD HL,00C9H
PUSH HL
LD HL,053EH
PUSH HL
CALL 現在SPのある番地
 このプログラムによってサブルーチンにできる。
HLにプログラムコードを逆順に2バイトづつ格納し、それを次々にスタックへプッシュしていく。その後、SPが指すアドレスをCALLするというもの。動的にプログラムコードを生成するため、非常に解析しづらいプログラムになる。
8:ペアレジスタの交換編
 BCとHLを入れ換える方法は普通、
PUSH BC
PUSH HL
POP BC
POP HL
の四段階を踏むが、特殊な方法として
PUSH BC
EX (SP),HL
POP BC
 これだと3バイトしか食わないし、スピードの速いこともいうことなし。
これは秀逸。一般的な方法では4バイトで42クロックかかるところ、3バイトで2クロック少ない40クロックで済む。ちなみに、HLがIXになった場合は、50クロック→44クロックと6クロックも少なくなる。