ステップ・バイ・ステップでPDP-7スライドショー
1. はじめてのプログラム
1.1. 実⾏を停⽌するだけのプログラムを作りながらSimHでのベアメタルプログラミングを紹介
SimH コマンド : examine と deposit
PDP-7 命令 : HLT命令
SimH コマンド : go
SimH コマンド : save と restore
SimH コマンド : help
simhスクリプトについて
基本的にアドレス0o100以降にプログラムを配置する
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=12
実装例
https://github.com/cupnes/pdp7-baremetal-programming-with-simh-samples/blob/main/01-halt.simh
2. テレタイプ
2.1. テレタイプで1⽂字出⼒する
テレタイプの紹介
SimH コマンド : show devices
PDP-7 レジスタ : ACレジスタ
PDP-7 命令 : TLS命令
PDP-7 命令 : JMP命令
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=34
実装例
TLS後、HLTするようにしてみる:
code:simh
d -m 100 TLS
d -m 101 HLT
# 例としてASCIIの'A'を設定
d ac 101
go 100
q
→ ただし、TLS命令で文字を出力用バッファへ設定後、直ちにHLT命令で停止させられてしまうので文字が出力されない
TLS後、無限ループするようにする:
code:simh
d -m 100 TLS
d -m 101 JMP 101
# 例としてASCIIの'A'を設定
d ac 101
go 100
q
→ 文字が出力されるようになった(終了しないので終了の際はCtrl+eでシミュレーション動作を停止させること)
2.2. 1⽂字ずつ出⼒を待ち合わせる
PDP-7 命令 : TSF命令・TCF命令
後の関数化のためにアドレス0o301に配置する
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=35
実装例
code:simh
d -m 301 TLS
d -m 302 TSF
d -m 303 JMP 302
d -m 304 TCF
d -m 305 HLT
# 例としてASCIIの'A'を設定
d ac 101
go 301
q
2.3. 1文字出力を関数にしてみる
「ACレジスタに設定されているASCII文字を出力する」関数を作る
JMS 300で呼び出せるように作成する
間接アドレス指定について
PDP-7 命令 : JMS命令とJMP I命令(JMP命令の間接アドレス指定)
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=36
実装例
code:simh
d -m 100 JMS 300
d -m 101 HLT
d -m 301 TLS
d -m 302 TSF
d -m 303 JMP 302
d -m 304 TCF
d -m 305 JMP I 300
# 例としてASCIIの'A'を設定
d ac 101
go 100
q
2.4 (時間があれば) 指定された⽂字列を出⼒する関数を作り「HELLO WORLD!」
2.4.1 まず「HELLO WORLD!」という文字列をメモリ上に設定する
扱いやすさから、18ビット毎に1文字ずつ並べることにする
NULL文字として0で終端することにする
depositコマンドの-aというswitchを使用すると楽
例) d -a 0 H (アドレス0へ'H'のASCII値を配置)
ただし、半角スペースやNULL文字には使えない
2.4.2 「ACレジスタに設定されているアドレスの文字列を出力する」関数を作る
JMS 400で呼び出せるように作成する
2.3で作った文字出力関数を使う
その他に新たに使用する命令は以下の通り
DAC命令・LAC命令・SZA命令・ADD命令
2.4.3 文字列出力関数を呼び出して動作確認
予めACレジスタに文字列のアドレスを設定しておく
どこか適当な所に「関数呼び出して、戻ってきたらHLTする」ように処理を書く
書いた処理をgoコマンドで実行してみる
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=37
実装例
https://github.com/cupnes/pdp7-baremetal-programming-with-simh-samples/blob/main/03-1-hello.simh
2.5. 1文字取得してみる
PDP-7 命令 : KRB命令
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=42
実装例
code:simh
d -m 100 KRB
d -m 101 JMP 100
go 100
e ac
q
→ 何らかのキーを押下後、Ctrl+eで抜けると、ACレジスタの内容が表示され、押下したキーのASCIIを確認できる(ビット7は無視していただいて・・)
2.6 ⼊⼒フラグを待ってから取得するようにする
PDP-7 命令 : KSF命令
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=43
実装例
code:simh
d -m 501 KSF
d -m 502 JMP 501
d -m 503 KRB
d -m 504 HLT
go 501
e ac
q
2.7. ⼊⼒された1⽂字を取得する関数を作る
「入力された文字をACレジスタへ設定する」関数を作る
JMS 500で呼び出せるように作成する
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=44
実装例
code:simh
d -m 100 JMS 500
d -m 101 HLT
d -m 501 KSF
d -m 502 JMP 501
d -m 503 KRB
d -m 504 JMP I 500
go 100
e ac
q
2.8. エコーバックを実装してみる
エコーバックプログラムとは
SimH コマンド : set tti fdx/hdx
fdxで、入力した文字が画面に自動出力されなくなる
まずは1文字取得と1文字出力を単に繰り返してみる
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=45
実装例
code:simh
d -m 100 JMS 500
d -m 101 JMS 300
d -m 102 JMP 100
go 100
q
※ JMS 500とJMS 300の関数の実装は省略(これまでと同じ)
→ ただ、実行してみるとEnter押下時にCRはするが、LFしない
2.9. 正しく改行できるようにする
Enter 押下で何を取得しているか確認
AC の値に応じて分岐させる
PDP-7命令 : SAD命令
LF出力処理を実装
PDP-7命令 : LAW命令
LF出力処理末尾から先頭に戻るようにすれば完成
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=47
実装例
https://github.com/cupnes/pdp7-baremetal-programming-with-simh-samples/blob/main/03-2-echoback.simh
3. ベクタースキャンディスプレイとタッチペン
3.1. Open SIMH同梱のテストプログラムを理解する
https://github.com/open-simh/simh/blob/cf47a20fd459d63be6c2e5a4728f2d2a31eaf884/PDP18B/tests/test340.simh
set debug stdoutとset dpy debugはコメントアウトしておく
PDP-7 命令 : IDLA命令・IDSI命令
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=52
3.2. 簡単な図形を描画してみる
# Small display list.の箇所にベクタモードの命令を追加して簡単な図形を描画してみる
Type 340命令を生成するシェルスクリプト
https://github.com/cupnes/sh_pdp7_svg2simh/blob/0790c440afff7e082d3c28013f25b139cb608f12/tools/type340_as
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=63
実装例
テストプログラムを改造してみる:
code:simh
set g2out disabled
# set debug stdout <- 処理速度に影響するので消したほうが良い
set dpy enabled
# set dpy debug <- 同じくコメントアウト
# Small test program.
dep -m 100 law 1000
dep -m 101 idla
dep -m 102 idsi
dep -m 103 jmp 102
dep -m 104 jmp 100
# Small display list.
#Go to point mode, set scale, set intensity.
dep 1000 020117
#Stay in point mode, set x=1000.
dep 1001 021000
#Go to vector mode, set y=1000.
dep 1002 301000
# 変更(ここから)
# ベクタモード : 線の描画 : 有り 、 X 座標 :+0o100 、 Y 座標 :+0
d 1003 200100
# ベクタモード : 線の描画 : 有り 、 X 座標 :+0 、 Y 座標 :+0o100
d 1004 240000
# ベクタモード : 線の描画 : 有り 、 X 座標 :-0o100 、 Y 座標 :+0
d 1005 200300
# ベクタモード : 線の描画 : 有り 、 X 座標 :+0 、 Y 座標 :-0o100
d 1006 740000
# パラメータモード : 描画停⽌ 、 STOP 割り込み設定
d 1007 003000
# 変更(ここまで)
dep pc 100
# Ready to go or single step.
3.3. sh_pdp7_svg2simhの紹介
https://github.com/cupnes/sh_pdp7_svg2simh/
3.4. ライトペンの紹介
https://ja.wikipedia.org/wiki/ライトペン
3.5. ライトペンを試す
PDP-7 命令 : IDSP命令・IDRS命令
線をタッチすると表示内容が消えてしまう問題を直す
備考:タッチペンの割り込みを解消させないと、Type 340の命令実行が止まって、描画内容が消えてしまう
test340.simhのIDLA命令とIDSI命令の間に処理を追加すれば良い
(時間があれば) ヒットしている間、"HIT"という文字列を出力するようにしてみる
同人誌の対応箇所
http://yuma.ohgami.jp/PDP7-BareMetal-Programming-with-SimH.pdf#page=63
実装例
線をタッチすると表示内容が消えてしまう問題を直すだけの実装例:
code:simh
# Small test program.
dep -m 100 law 1000
dep -m 101 idla
dep -m 102 idsp
dep -m 103 jmp 105
dep -m 104 idrs
dep -m 105 idsi
dep -m 106 jmp 102
dep -m 107 jmp 100
→ # Small test program.以外の部分は変更不要
→ IDRSを追加するだけでも問題ない
(時間があれば) ヒットしている間、"HIT"という文字列を出力するようにしてみるの実装例:
code:simh
set g2out disabled
set dpy enabled
set dpy debug
# 変更(ここから)
# 定数
# "HIT "
d -a 00 H
d -a 01 I
d -a 02 T
d 03 40
d 04 0
# 変更(ここまで)
# Small test program.
dep -m 100 law 1000
dep -m 101 idla
# 変更(ここから)
# ライトペンが描画箇所に触れていたら次の命令をスキップ
d -m 102 idsp
# - 触れていない場合: 触れている場合の処理を飛ばす
d -m 103 jmp 105
# - 触れている場合: 触れている場合の処理へジャンプ
d -m 104 jmp 110
dep -m 105 idsi
dep -m 106 jmp 102
dep -m 107 jmp 100
# 描画箇所に触れている場合の処理
# - ACレジスタへ0(アドレス0o160の値)を設定
d -m 110 lac 160
# - ACレジスタで指定されたアドレスの文字列を出力
d -m 111 jms 400
# - ヒット割り込みをクリア
d -m 112 idrs
# - 描画開始直後の処理まで戻る
d -m 113 jmp 102
# メイン処理内定数
# - 定数0
d 160 0
# 300: 指定された1文字を出力する関数
# ACレジスタに設定されている文字(ASCII)を出力する
# - 文字出力完了フラグをクリア
d -m 301 tcf
# - ACレジスタの文字を出力バッファへ設定
d -m 302 tls
# - 文字出力完了フラグがセットされていれば次の命令をスキップ
d -m 303 tsf
# - TSF命令へ戻る
d -m 304 jmp 303
# - return
d -m 305 jmp i 300
# 400: 指定された文字列を出力する関数
# ACレジスタにアドレスで指定されている文字列を出力する
# - ACレジスタの値(文字列の先頭アドレス)をアドレス0o460へ書き込み
d -m 401 dac 460
# - アドレス0o460に書かれているアドレスから次の文字をACレジスタへ取得
d -m 402 lac i 460
# - 取得した文字が0(NULL)なら次の命令をスキップ
d -m 403 sza
# - NULLでないなら、文字出力へ
d -m 404 jmp 406
# - return
d -m 405 jmp i 400
# - ACレジスタに設定されている文字を出力する関数呼び出し
d -m 406 jms 300
# - アドレス0o460の値(今出力した文字のアドレス)をACレジスタへ設定
d -m 407 lac 460
# - ACレジスタへ定数1を加算(アドレスを次の文字へ進める)
d -m 410 add 461
# - ACレジスタの値をアドレス0o460へ書き戻す
d -m 411 dac 460
# - 次の文字の取得へ戻る
d -m 412 jmp 402
# 関数内変数/定数
# - 460: 次に出力する文字のアドレス
# - 定数1
d 461 1
# 変更(ここまで)
# Small display list.
#Go to point mode, set scale, set intensity.
dep 1000 020117
#Stay in point mode, set x=1000.
dep 1001 021000
#Go to vector mode, set y=1000.
dep 1002 301000
# ベクタモード : 線の描画 : 有り 、 X 座標 :+0o100 、 Y 座標 :+0
d 1003 200100
# ベクタモード : 線の描画 : 有り 、 X 座標 :+0 、 Y 座標 :+0o100
d 1004 240000
# ベクタモード : 線の描画 : 有り 、 X 座標 :-0o100 、 Y 座標 :+0
d 1005 200300
# ベクタモード : 線の描画 : 有り 、 X 座標 :+0 、 Y 座標 :-0o100
d 1006 740000
# パラメータモード : 描画停⽌ 、 STOP 割り込み設定
d 1007 003000
dep pc 100
# Ready to go or single step.
4. スライドショーソフト作成
4.1. 設計について考える
ある画像を表示していて、別の画像を表示する(スライド移動)にはどうすれば良いか?
次のスライドへ進む/前のスライドへ戻る処理のトリガーには何を使うか?
次のスライドへ進む/前のスライドへ戻る処理のトリガーの条件分岐はどこへ入れると良いか?
プログラムの自動生成などはどうするか?
4.2. 実装する
実装例
https://github.com/cupnes/sh_pdp7_svg2simh/blob/main/make_slideshow.sh
./make_slideshow.sh <SVGファイル> <SVGファイル> ...のように指定して実行すると、それらをスライドショーするresult.simhが生成される
スライドショーの操作
テレタイプへのキー入力:次のスライドへ進む
ライトペンによる線へのタッチ:前のスライドに戻る