TOPPRM: MOV.L M_OK1,R2 ; "OK" BSR PUTSTR ; を表示する NOP ; (遅延スロット) |
TOPLEV: MOV.L WRKTOP3,R15 ; ワークエリアの先頭=ハードスタックの初期値 LDC R15,GBR ; GBR初期化 MOV.L @(SPLIM-WRKTOP,GBR),R0 ; ソフトスタックの初期値 MOV R0,R14 ; ソフトスタック初期化 |
MOV #0,R0 ; 0で BSR GETLN ; 1行入力 MOV.B R0,@(RUNFLG-WRKTOP,GBR) ; RUNFLG をクリヤして BT TOPLEV ; CTRL−Cなら破棄 |
BSR LTOUPP ; 大文字に変換する NOP ; (遅延スロット) MOV.L LINBUF4,R3 ; 行入力バッファの先頭番地 BSR SKIPSP ; 空白を飛ばす NOP ; (遅延スロット) |
BSR GETLIT ; 行番号はあるか? NOP ; (遅延スロット) BT TOPLV1 ; あれば TOPLV1 へ(R2には行番号) MOV #0,R2 ; なければR2を0にして BRA TOPLV2 ; TOPLV2 へ |
TOPLV1: TST R2,R2 ; R2(入力された行番号)が0なら BT JBADLIN2 ; JBADLIN2 へ ADD #1,R2 ; R2が H'FFFFFFFF TST R2,R2 ; なら BT JBADLIN2 ; JBADLIN2 へ ADD #-1,R2 ; 1足したぶん戻す |
TOPLV2: MOV R2,R0 ; R2(入力された行番号)を MOV R0,@(ENTNO-WRKTOP,GBR) ; ENTNO に格納 |
MOV.B @R3,R0 ; 行番号の後の最初の数字じゃない文字 CMP/EQ #H'20,R0 ; が空白なら BF TOPLV3 ; TOPLV3 へ ADD #1,R3 ; 空白1文字スキップする TOPLV3: MOV R3,R0 ; 文字ポインタを MOV.L R0,@(GTPTR-WRKTOP,GBR) ; GTPTR に格納 |
MOV.L @(ENTNO-WRKTOP,GBR),R0 ; ENTNO が CMP/EQ #0,R0 ; 0でなければ(行番号付きなら) BF ENTPRG ; ENTPRG へ |
; (ダイレクト実行するケース) BSR EXELIN ; EXELIN を呼びだす MOV R3,EXEP ; 文字ポインタを EXEP にコピーして(遅延スロット) BRA TOPLEV ; 呼びだし後 TOPLEV に戻る NOP ; (遅延スロット) |
トップレベルプロンプトから呼ばれる、行実行ルーチンです。(ちなみにRUNコマンドからも呼ばれます。RUNコマンドはメモリに蓄えられたプログラムの1行1行に対して順次このルーチンを呼び出すことによってプログラムの実行をするわけです。)
EXELIN: STS.L PR,@-R15 ; PR保存 MOV #0,R0 ; 0で MOV.B R0,@(EXLFLG-WRKTOP,GBR) ; EXLFLG をクリヤ |
EXELLP: MOV #0,R0 ; 0で MOV.B R0,@(EXSFLG-WRKTOP,GBR) ; EXSFLG をクリヤ BSR CHKBRK ; CTRL−Cキーのチェック NOP ; (遅延スロット) |
BSR SKIPSP ; 空白を飛ばす MOV EXEP,R3 ; EXEP をR3にコピーして(遅延スロット) CMP/EQ #0,R0 ; 行末なら BT EXELNE ; 行実行終了 |
MOV.L STATM1,R2 ; 文・コマンドのネームテーブル BSR SCAN ; SCAN 呼びだし NOP ; (遅延スロット) BT EXELN1 ; 一致するキーワードがあったら EXELN1 へ |
;(一致するキーワードが無かった場合) BSR QLET ; 代入文か? NOP ; (遅延スロット) ;(代入文ならR2には変数の番地が入っている) BF EXELN2 ; 代入文でなければ EXELN2 へ ;(代入文だった場合) BSR GETFRM ; GETFRM を呼びだし MOV.L R2,@-R15 ; 変数の番地を保存(遅延スロット) ;(R2には式の値が入っている) MOV.L @R15+,R0 ; 変数の番地を取りだし BRA EXELN3 ; EXELN3 へ MOV.L R2,@R0 ; 式の値を変数に代入して(遅延スロット) |
;(一致するキーワードがあった場合) EXELN1: JSR @R2 ; そのキーワードの処理ルーチンを呼びだす MOV R3,EXEP ; R3を EXEP に書き戻す MOV.B @(EXLFLG-WRKTOP,GBR),R0 ; EXLFLG が CMP/EQ #0,R0 ; 0でなければ BF EXELNE ; 行実行終了 |
EXELN2: MOV.B @(EXSFLG-WRKTOP,GBR),R0 ; EXSFLG が CMP/EQ #0,R0 ; 0でなければ BF EXELLP ; ループ先頭に戻る MOV EXEP,R3 ; EXEP をR3にコピー |
;(文の実行が終わった後の処理) EXELN3: BSR SKIPSP ; 空白を飛ばす NOP ; (遅延スロット) MOV R3,EXEP ; R3を EXEP に書き戻す CMP/EQ #0,R0 ; 行末なら BT EXELNE ; 行実行終了 CMP/EQ #H'27,R0 ; 注釈なら BT EXELNE ; 行実行終了 CMP/EQ #H'3A,R0 ; コロンでなければ BF JSYNERR4 ; SYNTAX ERROR にする ADD #1,R3 ; コロンをスキップ BRA EXELLP ; ループ先頭に戻る MOV R3,EXEP ; R3を EXEP に書き戻す(遅延スロット) |
EXELNE: LDS.L @R15+,PR ; PR復帰 RTS ; リターン NOP ; (遅延スロット) |
本来「低レベルテキスト解析」の回で説明すべきルーチンでしたが、すっぽり抜け落ちていました。この手のルーチンはさんざん説明したので、リストを挙げるだけにとどめます。みなさん、練習問題だと思って各自で読解してみてください。
QLET: STS.L PR,@-R15 ; PR保存 BSR SKIPSP ; 空白を飛ばす MOV EXEP,R3 ; EXEP をR3にコピーして(遅延スロット) BSR GETVAR ; 変数かどうかチェック MOV.L R3,@-R15 ; R3を保存して(遅延スロット) BF QLETN ; 変数でなければ否定的終了 ;(変数だった場合、R2には変数の番地が入っている) BSR SKIPSP ; 変数の後の空白を飛ばす NOP ; CMP/EQ #H'3D,R0 ; '=' か? BF QLETN ; 違ったら否定的終了 ADD #1,R3 ; '=' をスキップ MOV R3,EXEP ; R3を EXEP に書き戻す ADD #4,R15 ; スタックに保存したR3を破棄 LDS.L @R15+,PR ; PR復帰 RTS ; リターン SETT ; Tビットをセットする(遅延スロット) ;(否定的終了処理) QLETN: MOV.L @R15+,R3 ; R3復帰 LDS.L @R15+,PR ; PR復帰 RTS ; リターン MOV R3,EXEP ; Tビットをクリヤする(遅延スロット) |