標準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
前へ
次へ
ホームページトップへ戻る