エピ18 まとめ −−− SP5030のコードを調べました
***
エピ18 まとめ −−− SP5030のコードを調べました
***
カセットテープを聴こうと思って始めたのですが、...。
SP5030のコードが手に入って思わず深入りしてしまいました。少しは後悔してる? いいえ、基本駄文で、いつも迷走してますから止む得ないことです。
...。orz
ここで一旦まとめて、次に進みたいと思います。
***
Z80の機械語はシンプルで、ニモニックに少々癖がありますが、逆アセンブルは簡単です。
ですが。コードの解読に入ると難解でした。意図不明なコードの塊。それにコードとデータの区別が必要で、自己書換も可能では何ら頼りになるものがなく。コールしてもリターンしないし。
最初から1ステップ毎に進むしかないことが分かりました。
それでもジャンプテーブルが特定できて、共通ライブラリの解読が進むと作業は捗りました。
詳細は別途に整理するとして、以下にSP5030のコードについてまとめますね。
*
■ 1200 〜 124C : 初期化処理(エピ5で解説)
各種の初期化をします。ワークエリアやスタックとか。時計は0時0分0秒に設定。
それから「 * SHARP BASIC SP-5030」とメモリサイズを表示します。RAM48Kの機種ならメモリは 34680 BYTES です。
■ 124D 〜 12DF : メインループ(エピ6とエピ7で解説)
キー入力待ちをして、プログラムを入力したり、直接実行命令文を実行したりします。
プログラムは "RUN" 命令文を実行すると実行が始まって、命令文を順番に実行して行きます(エピ8)。
■ 12E0 〜 13BB : エラーメッセージの処理(エピ5で解説)
エラーの場合はここにジャンプしてきて、エラーメッセージを表示した後、メインループに戻ります。ワークエリアやスタックはメインループで初期化します。
■ 13BC 〜 13C8 : 4565h に 00h, 01h, 02h をセット(エピ6で解説)
[4565h] に値をセットするだけの専用ルーチンです。このワークエリアを特別扱いする理由があるのかな?
■ 13C9 〜 1614 : 入力文を中間コードに変換(エピ6で解説)
変換1と変換2があります。変換1が中間コードへの変換で、変換2は無意味な感じでした。
ここに中間コードの順番で予約語のデータがあります。
中間コードの構成は、
80h〜A8h: 命令文
B0h〜BFh: 演算子(CFh も演算子です)
C0h〜CBh: 文字列関数
D0h〜DBh: 数値関数
です。この他に ADh("THEN"), AEh("TO"), AFh("STEP") があります。この "命令文" は正確には命令文用の予約語のことですね。
■ 1615 〜 1628 : 定数データ(5バイトx4個)
4個の定数とは 1 と 0 と -1 と π です。
■ 1629 〜 199D : 共通ライブラリ
共通ライブラリ? というか雑多なルーチン。もう少し整理すると構成が見えてくるかも。リターン番地を操作するルーチンが複数あり注意です。
<整理中>
■ 199E 〜 1A5F : 命令文の分岐処理(エピ7で解説)
命令文の中間コードは 80h〜A8h です。直接実行することも、文番号を付けてプログラムとして記憶して "RUN" 命令で実行することもできます。
命令文の中間コードでテーブルジャンプして、ジャンプ先で命令文の処理をした後、ここに戻ってきます。次の命令文があれば処理を続けて、終端(0Dh)ならメインループに戻ります。プログラムの実行中なら次の文に進みます。これがプログラムのループです(エピ8見てね)。
命令文(80h〜A8h)のジャンプテーブルがあります。
■ 1A60 〜 21FD : 命令文の分岐先・その1
命令文の処理ルーチンたちです。中間コードでは 80h〜90h と 94h〜9Bh です。
でも最初のルーチンは "NEW" (84h) 命令です。中間コードの順で並んでいるのではないです。
"RUN" (83h) と "END" (8Fh) はエピ8で見ました。"LOAD" (91h) と "LIST" (82h) はエピ10です。"LET"(86h) はエピ12。それから "FOR" (87h)、"NEXT" (8Dh)、"GOSUB" (8Ch)、"RETURN" (8Bh) はエピ13で見ました。
■ 21FE 〜 25FE : 数式処理のルーチン達(エピ14、15、16で解説)
演算子の優先順位を実現する4つのルーチンの連鎖(21FFh, 2251h, 22B2h, 22C5h)。それから演算子により分岐処理するルーチン(22D4h)と、値を処理するルーチン(231Dh)がありました。
22D4h には技巧がありました。これが不可解なコードの根源なのでした。
231Dh が樹海の正体でした。値には数値と文字列と関数と各種の変数があります。DEF_FN で定義した FNx もありますし、π や TI$ のような定数(変数?)もあります。これらを if ... else で分岐しているから樹海になるのです。更には。関数なら引数があるので、引数の評価をするために 2251h をコールしますし、変数だって、配列変数なら添字の評価で 2251h を呼び出します。値の評価では変数や関数が登場して、...グルグルします。
ジャンプテーブルが3つあります。演算子と関数はこのジャンプテーブルで分岐して処理します。
■ 25FF 〜 27C5 : 文字列関数の分岐先
文字列関数(C0h〜CBh)の処理ルーチンです。最初は C0h の "LEFT$(" 関数で、次は "RIGHT$("(C1h)、"MID$("(C2h) と割と中間コードの順番で並んでます。"VAL(" と "ASC(" が逆転しているくらい。
数値関数の "ABS("(D9h) と "SGN("(DAh) がここに入ってます。仲間外れか。
それと、"AND"(B9h), "OR"(BAh), "NOT"(BBh) もここに入ってますが、エラー表示にジャンプするだけです。
■ 27C6 〜 2D07 : 命令文の分岐先・その2
命令文の処理です。最初は "BYE" 命令。中間コードでは 91h〜93h と 9Ch〜A8h です。
その1とその2の違いはなんでしょう? 91h は "LOAD"、92h は "SAVE"、93h は "VERIFY" ですけど。
■ 2D08 〜 3AEC : 演算子と数値関数の分岐先
演算子(B0h〜BFh,CFh)と数値関数(D0h〜DBh)の処理ルーチンです。
演算子は '+','-','*','/' などです。比較演算子もここです。
数値関数には INT() や RND(), SIN(), COS(), TAN() などがあります。
■ 3AED 〜 : ???
<未整理>
■ 3D24 〜 : 1行入力処理
オートリピート機能がオフならROMルーチンをコールするだけです。ここにはオートリピートがオンの場合のコードがあります。
<未整理>
■ 3EF1 〜 : I/Oを行なう処理(コール元が不明)
<未整理>
■ 4049 〜 413F : LOAD 命令のサブルーチン(エピ9と10で解説)
ROMルーチンと同じ構成で、要所でROMルーチンをコールしています。ROMルーチンに支障があって改善が必要になったのでしょうか。
***
**
*
不思議なコードがあって(処理の内容は分かるけど)意図が分からなくて悩みました。
それがあるとき、別のコードと合せて見ると連携してひとつの処理が成立している! ...って気が付いたときには幸せな気分になります(...、とても安上がりな幸せ)。
まだ謎や課題が残っているので隙間時間を見つけて調べてみるかもです。
***
間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!
***
2026.3.31 推敲




