目次
前
次
モニタ開発
パーソナルコンピュータと同様、ハードウエアを直接
動かすためBIOS(Basic Input Output System)を用意
しておけば、開発が楽になります。
BIOS作成は大げさなので、モニタを作成します。
モニタは、ハードウエアを直接動かすコードの集合体
なので、接続されている周辺ICのレジスタを操作する
コードが必要です。
端末から操作できるように、コマンドインタプリタと
コマンドを定義します。
最初のコマンドインタプリタは、単純に文字比較とします。
コマンドインタプリタは、サブルーチン構成にします。
CMD_INT:
push af
push bc
push ix
; set serial buffer
ld ix,SBUF
; get 1 command charactor
ld a,(ix)
; judge command
cp 'I'
call z,CMD_I
cp 'O'
call z,CMD_O
cp '?'
call z,CMD_HELP
;
pop ix
pop bc
pop af
ret
CMD_I:
ret
CMD_O:
ret
CMD_HELP:
ret
コマンドは、1文字として'I'と'O'を用意します。
シリアルバッファは、ラベルSBUFで指定しておき
SRAMの中に、256バイト分確保します。
SBUF: DEFS 256
コマンド'I'の仕様を考え定義します。
I/Oアドレスは、0〜255なので、16進数2けたで
指定します。このアドレスを、SBUFの中に次のように
入っているとして、動かします。
コマンド'I'は、デリミタを'\r'として3バイトとします。
仕様を確定したので、サブルーチンの内容を確定します。
CMD_I:
; store
push af
push bc
; get I/O address
ld c,(ix+1)
; get data
in a,(c)
; show
call SHOW_BYTE
; resume
pop bc
pop bc
;
ret
サブルーチンSHOW_BYTEは、別途定義します。
コマンド'O'の動作を考え定義します。
I/Oアドレスを0〜255、データを0〜255と
して、各々16進数2けたで指定します。
アドレス、データがSBUFの中に入っているとして
サブルーチンを構成します。
CMD_O:
; store
push af
push bc
; get I/O address
ld c,(ix+1)
; get data
ld a,(ix+2)
; impress
out (c),a
; resume
pop bc
pop bc
;
ret
ここまでで、周辺ICレジスタを操作できるように
なったので、次にメモリの内容を設定、表示する
処理を考えます。
メモリ内容表示は、次のようにします。
8000: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
8010: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
8020: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
8030: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
8040: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
8050: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
8060: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
8070: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
8080: 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
8090: 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
80a0: A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
80b0: B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
80c0: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
80d0: D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
80e0: E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
80f0: F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
アドレスを16進表示後、コロンを入れ16個の数値を
16進で表示します。
コマンドは'D'(dump)として、256バイトを表示します。
メモリのアドレスが必要なので、次のようにSBUFを
利用します。
コマンドインタプリタに、'D'コマンドを付け加えます。
CMD_INT:
push af
push bc
push ix
; set serial buffer
ld ix,SBUF
; get 1 command charactor
ld a,(ix)
; judge command
cp 'I'
call z,CMD_I
cp 'O'
call z,CMD_O
cp '?'
call z,CMD_HELP
cp 'D'
call z,CMD_D
;
pop ix
pop bc
pop af
ret
'D'コマンド用のサブルーチンを考えます。
- 16進数値を1けたの数字(0〜9、A〜F)に変換
- コンソールに1文字表示
動作を考えて、各サブルーチンの名前を決めます。
サブルーチン名を与えると、実現コードが明確になります。
- h2a 16進数値を1けたの数字(0〜9、A〜F)に変換
- rs_putc コンソールに1文字表示
2つのサブルーチンが存在するとして、'D'コマンドを
記述してみます。
CMD_D:
push af
push bc
push de
push hl
push ix
; get address
ld ix,MADR
ld h,(ix+0)
ld l,(ix+1)
; set counter
CMD_D0:
ld c,16
ld a,c
CMD_D1:
cp 0
jr z,CMD_D_END
; show address
ld a,h
; higher nibble => lower nibble
srl a
srl a
srl a
srl a
; hexadecimal => neumeric code
call h2a
; show upper
call rs_putc
ld a,h
and 0fh
; hexadecimal => neumeric code
call h2a
; show lower
call rs_putc
; show "00:"
ld a,'0'
call rs_putc
ld a,'0'
call rs_putc
ld a,':'
call rs_putc
;
ld b,16
CMD_D2:
ld a,(hl)
; store
ld c,a
; higher nibble => lower nibble
srl a
srl a
srl a
srl a
; hexadecimal => neumeric code
call h2a
; show
call rs_putc
; get lower nibble
ld a,c
and 0fh
; hexadecimal => neumeric code
call h2a
; show
call rs_putc
; get space
ld a,20h
call rs_putc
; address increment
inc hl
; check 1 line
djnz CMD_D2
; send CR
ld a,0dh
call rs_putc
; send LF
ld a,0ah
call rs_putc
; counter decrement
dec c
ld a,c
jr CMD_D1
CMD_D_END:
pop ix
pop hl
pop de
pop bc
pop af
;
ret
サブルーチンを定義するには、コーリングシーケンス
を決めると、利用レジスタやメモリ領域が見えてきます。
サブルーチンh2aを定義します。
コーリングシーケンスは、以下とします。
16進数値4ビットをレジスタAに入れて、コール。
結果は、レジスタAに入っている。
16進数値の範囲外の場合、下位4ビットを16進数値
とみなして、変換する。
サブルーチンh2aは、以下です。
h2a:
;*** get lower 4 bits ***
add a,0fh
;*** 0 => 9 ***
or 30h
;*** ? A => F ***
cp 3ah
jr c,h2a_end
add a,07h
h2a_end:
ret
relative jumpを利用して、リロケータブルの
コードにしました。
モニタとして、他にどんな機能があればよいか
6800のデバッグモニタとして有名だったという
MIKBUGのコマンドを調べてみました。
MIKBUGのソースコードをWEBサイトでみることができたので
サポート機能を拾い出してみました。
- プログラムのメモリへのロード
- レジスタの内容表示
- メモリダンプ
- メモリ内容の表示/変更
- プログラム実行
- パラレルポートを使ったシリアル入出力
- 割込みの補助
テレタイプのASR-300シリーズや紙テープを
利用し、わずか768バイトで上の機能を
実現していたことに、驚きました。
プログラムのロードと実行は必要なので
この2つの実装をします。
プログラム実行
プログラム実行は、分岐命令を使います。
Z80で使える分岐命令は、絶対アドレス指定で
リストすると、以下。
- JP (HL)
- JP (IX)
- JP (IY)
- JP absolute address
分岐命令だけでは、プログラムを実行して
モニタに戻ってこれないので、対象となる
コードの最後には、モニタプログラムへと
戻ってくるコードを入れます。
次のようなモジュールになります。
XTST:
; store
push af
push bc
push de
; insert target code
;
;
; resume
pop de
pop bc
pop af
; return to monitor
JP monitor
モジュールプログラムのアドレス格納に2バイトの領域を
用意しておきます。モニタは、この2バイトをHLレジスタ
ペアに入れて、プログラムを実行します。
MDADR: DS 2
; get address
LOAD HL,(MDADR)
; branch
JP (HL)
プログラムロード
(under construction)
目次
前
次