標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第153回]

●LXI、PUSH、POPを使ったテストプログラムです

0000 310000   LXI SP,0000
0003 3E55     MVI A,55
0005 013412   LXI B,1234
0008 117856   LXI D,5678
000B 21BC9A   LXI H,9ABC
000E C5       PUSH B
000F D5       PUSH D
0010 E5       PUSH H
0011 F5       PUSH PSW
0012 F1       POP PSW
0013 E1       POP H
0014 D1       POP D
0015 C1       POP B
0016 C30E00   JMP 000E

おもにPUSH、POPの動作を確かめるためのテストプログラムです。

LXI SPはSP(スタックポインタ)にスタックトップのアドレスをセットする命令です。
PUSH、POP(およびCALL、RET)を使うプログラムでは、プログラムの先頭でSP(スタックポインタ)にスタックトップのアドレスを入れておく必要があります。
8080(Z80も同じ)では、リセットによってPC(プログラムカウンタ)は0000にクリアされますが、SPを含めてその他のレジスタはクリアされません。

ちょっと考えると、開発者の手抜きのようにも思えますが、もともとCPUはプログラマによって最大限、自由にコントロールできる、というコンセプトのもとに作られたもの、と考えられます。
PC(プログラムカウンタ)だけは、必ず0000からスタートしてくれなければ困りますから、リセットによって0000にクリアされます。
しかし、そのほかのレジスタは、プログラマが必要に応じて設定するから、勝手にクリアしたりしないでよ、ということなのだと思います。

実際、用途によっては、たとえリセットされたとしても、それ以前の途中経過を保持していて、そこから再スタートしたい、ということもあると思います。
え。そんなことって、あるの?

レベルは全く違いますけれど、パソコンが突然ハングアップしてしまったり、うっかり誤操作などでリセットして(リセットされて)しまったときなど、
「あああっ、作業中のファイルがぁ…」
という経験をしたことは、ありませんか?

そんなときには、
「なんで、勝手にクリアしたりするんだよぉ」
って、思わず、どついてやりたくなりますねぇ。

ま、現行のWindowsパソコンのCPUでは、たとえレジスタやメモリを現状のまま保存したとしても、なにしろ資源をdynamic(動的)に使っているのですから、もとの状態を復元することは、多分不可能でしょう。
バックアップファイルをリアルタイムに保存するような、バックグラウンドで働くツールの助けが不可欠です。

幸いにして、8080やZ80は通常の使い方では、もちろんstatic(静的)な動作ですから、リセットによって、レジスタを一律に0クリアしてしまうよりは、そのまま保存してくれた方が、よりメリットがあります。
どのみち、SP(スタックポインタ)を含めて、汎用のレジスタはいつも初期値が0である、とは限りません。
どうせプログラムによってさまざまな値を初期設定することになるのですから、リセットによって汎用レジスタをクリアするなどということは、まさに「余計なこと」です。
スタックも、いつもRAMの終りに置く、とは限りません。
むしろ、RAMの途中に置くことの方が多いと思います。

また、余談になってしまいますが、参考までに…。

●ND80Kのメモリマップです

当社製品ND80Kのメモリマップです。

FFFF LED表示用セグメントデータバッファ bW
FFFE LED表示用セグメントデータバッファ bV
FFFD LED表示用セグメントデータバッファ bU
FFFC LED表示用セグメントデータバッファ bT
FFFB LED表示用セグメントデータバッファ bS
FFFA LED表示用セグメントデータバッファ bR
FFF9 LED表示用セグメントデータバッファ bQ
FFF8 LED表示用セグメントデータバッファ bP
FFF7 LED表示用データレジスタ bS
FFF6 LED表示用データレジスタ bR
FFF5 LED表示用データレジスタ bQ
FFF4 LED表示用データレジスタ bP
FFF3  トレースカウンタ(H)
FFF2  トレースカウンタ(L)
FFF1  ブレイクアドレス(H)
FFF0  ブレイクアドレス(L)
FFEF  アドレスレジスタ(H)
FFEE  アドレスレジスタ(L)
FFED  データレジスタ(H)
FFEC  データレジスタ(L)
FFEB  CPUレジスタセーブエリア  A
FFEA  CPUレジスタセーブエリア  F
FFE9  CPUレジスタセーブエリア  B
FFE8  CPUレジスタセーブエリア  C
FFE7  CPUレジスタセーブエリア  D
FFE6  CPUレジスタセーブエリア  E
FFE5  CPUレジスタセーブエリア  H
FFE4  CPUレジスタセーブエリア  L
FFE3  CPUレジスタセーブエリア  SP(H)
FFE2  CPUレジスタセーブエリア  SP(L)
FFE1  CPUレジスタセーブエリア  PC(H)
FFE0  CPUレジスタセーブエリア  PC(L)
FFDF  CPUレジスタセーブエリア  IX(H)
FFDE  CPUレジスタセーブエリア  IX(L)
FFDD  CPUレジスタセーブエリア  IY(H)
FFDC  CPUレジスタセーブエリア  IY(L)
FFDB  CPUレジスタセーブエリア  A’
FFDA  CPUレジスタセーブエリア  F’
FFD9  CPUレジスタセーブエリア  B’
FFD8  CPUレジスタセーブエリア  C’
FFD7  CPUレジスタセーブエリア  D’
FFD6  CPUレジスタセーブエリア  E’
FFD5  CPUレジスタセーブエリア  H’
FFD4  CPUレジスタセーブエリア  L’
FFD3  CPUレジスタセーブエリア  I
FFD2  CPUレジスタセーブエリア  R
FFD1  トレース、レジスタダンプ制御フラグ
FFD0  I/O、レジスタモード制御フラグ
FFCF  レジスタモード制御フラグ
FFCE  ブレイクコード保存用レジスタ
FFCD
FFCC
FFCB  LED表示割り込みプログラムワークレジスタ(H)
FFCA  LED表示割り込みプログラムワークレジスタ(L)
FFC9  シリアルインターフェース用ワークレジスタ
FFC8  シリアルインターフェース用ワークレジスタ
FFC7  シリアルインターフェース用ワークレジスタ
FFC6  EI記録レジスタ
FFC5
FFC4
FFC3
FFC2
FFC1
FFC0
FFBF
FFBE
FFBD
FFBC  RST7ジャンプ先アドレス(H)
FFBB  RST7ジャンプ先アドレス(L)
FFBA  RST7ジャンプコード(C3H)
FFB9  システムスタック
:
:
:
:
F800
F7FF  ユーザースタック
:
:
:
:

システムスタックはRAMの終り、FFFFからではなくて、それよりもずっと前の方、FFB9からになっています。これはシステムプログラムのためのスタックエリアで、ユーザーが使うことはできません。
ユーザーは、それよりもさらに前の方、F7FFから前をスタックエリアとして使います。

スタックはメモリの後ろから前方(若いアドレス)に向かって使われていきます。
そのときの状況によってどこまで消費されるかわかりません。
場合によっては、プログラムエラーなどで、どんどんスタックを食いつぶしてしまって、ついにはプログラムまで破壊して、そこで止まるか、暴走するか、という事態も考えられます。
したがって、破壊されてしまっては困る大事なシステムワークエリアは、スタックよりも後ろに置いた方が安全なのです。
もっとも、プログラムエラーによっては、逆にスタックよりも後ろの方を破壊してしまうこともありますから、絶対に安全ということはありません(プログラムエラーの結果は基本的に、「何でもあり」です。恐いですねー)。

以上、余談でした。

●テストプログラムの説明に戻ります

さて、今回は簡単なテストプログラムですから、スタックはRAMの終りに置くことにします。
LXI SP命令でスタックポインタにスタックアドレスをセットするときは、スタックトップよりも+1大きい値を指定します。
今回はFFFFから前をスタックとして使うことにします。
FFFFよりも+1進んだ0000を指定しますから、LXI SP,FFFFではなくて、LXI SP,0000です。

LXI B、LXI D、LXI HはペアレジスタBC、DE、HLに16ビットのデータを格納する命令です。
Aレジスタに対しては、8ビットデータを格納する、MVI命令で値をセットします。
そのあとは、PUSHでスタックにレジスタの値を退避し、そしてその値をふたたびスタックからレジスタに戻す、という動作をひたすら繰り返します。

このテストプログラムは、数時間実行してみましたが、レジスタとスタックとの間で、同じ値をやりとりするだけで、LED表示は全く変化しませんから、面白くも楽しくもありません。
次回はもう少し、ましなプログラムを作ってテストしてみたいと思います。
2009.2.4upload

前へ
次へ
ホームページトップへ戻る