ENTPRG: MOV R0,R2 ; 行番号をR2へ MOV.L @(GTPTR-WRKTOP,GBR),R0 ; 入力されたテキストの先頭番地 MOV R0,R3 ; をR3へ BSR SKIPSP ; 空白をとばす MOV R3,R4 ; R3をR4に保存(遅延スロット) MOV R4,R3 ; R3(テキストの先頭番地)復帰 CMP/EQ #0,R0 ; SKIPSPが返した文字をチェック BT DELLIN ; 空テキストだったら行削除 |
MOV #MAXLL+6,R13 ; 入力可能な最大バイト数 MOV #6,R1 ; 長さカウンタ=最小バイト数(行番号+長さ+行末) EXTU.B R13,R13 ; 127より大きいのでEXTUする ENTPL: CMP/EQ R13,R1 ; 長さカウンタ=最大バイト数なら BT ENTP1 ; ENTP1へとぶ MOV.B @R3,R0 ; その位置に CMP/EQ #0,R0 ; 行末の0はあるか? BT ENTP2 ; あればENTP2へとぶ ADD #1,R3 ; ポインタインクリメント BRA ENTPL ; ENTPLに戻る ADD #1,R1 ; 長さカウンタインクリメント(遅延スロット) ; 最大バイト数まで行末が見つからなかった場合 ENTP1: MOV #0,R0 ; 強制的に MOV.B R0,@R3 ; 行末の0を置く |
ENTP2: MOV R1,R0 ; 長さカウンタの下位2ビットが0なら TST #3,R0 ; (つまり4で割り切れるなら) BT ENTP3 ; ENTP3へとぶ MOV #0,R0 ; でなければ0を ADD #1,R3 ; ポインタインクリメントして MOV.B R0,@R3 ; もう1つおく BRA ENTP2 ; ENTP2に戻る ADD #1,R1 ; 長さカウンタインクリメント |
ENTP3: MOV R1,R0 ; 長さをR0へ BSR SCNHSL ; SCNHSLで入力すべき番地を探す MOV.B R0,@(ENTLEN-WRKTOP,GBR) ; R0をENTLENにストア(遅延スロット) MOV R3,R0 ; 入力すべき番地を MOV.L R0,@(ENTADR-WRKTOP,GBR) ; ENTADRにストア |
CMP/EQ R2,R1 ; すでに同じ行番号の BF INSLIN ; 行がなければINSLINへとぶ |
ADD #4,R3 ; 見つけた行の行番号をスキップ MOV.B @R3+,R2 ; 見つけた行の長さ MOV.L @(BASEND-WRKTOP,GBR),R0 ; BASICプログラムの終わり EXTU.B R2,R2 ; 長さバイトを符号無し化 ADD R2,R3 ; 次の行の先頭番地 SUB.L R3,R0 ; 転送する長さを計算 MOV.L R0,@(GTLEN-WRKTOP,GBR) ; 転送する長さをGTLENにストア |
MOV.B @(ENTLEN-WRKTOP,GBR),R0 ; 入力された行の長さ MOV R0,R1 ; ADD #-5,R1 ; 行番号と長さバイトぶん引く SUB R2,R1 ; 番地の増加分を計算 TST R1,R1 ; BT REPLNX ; 同じ長さならREPLNXへ CMP/PL R1 ; BT INCLIN ; 増える場合はINCLINへ |
MOV R3,R2 ; R3には次の行の先頭番地 ADD R1,R2 ; 転送先番地の計算 MOV.L @(GTLEN-WRKTOP,GBR),R0 ; 転送する長さ BSR LDIR ; 次の行以降を前にずらす MOV R0,R1 ; 転送する長さをR1に(遅延スロット) MOV R2,R0 ; MOV.L R0,@(BASEND-WRKTOP,GBR) ; BASEND と FREE を設定しなおす BRA REPLNX ; REPLNX に飛ぶ MOV.L R0,@(FREE-WRKTOP,GBR) ; (遅延スロット) |
INCLIN: MOV.L @(BASEND-WRKTOP,GBR),R0 ; 転送元番地 BRA INSLNX ; INSLNX へ飛ぶ MOV R0,R3 ; 転送元番地をR3へ(遅延スロット) |
INSLIN: MOV R0,R3 ; 見つけた行の番地 MOV.L @(BASEND-WRKTOP,GBR),R0 ; BASICプログラムの終わり MOV R0,R2 SUB R3,R0 ; 転送する長さを計算 MOV.L R0,@(GTLEN-WRKTOP,GBR) ; 長さを GTLEN にストア MOV.B @(ENTLEN-WRKTOP,GBR),R0 ; 入力された行の長さ=番地増加分 MOV R2,R3 ; BASEND=転送元番地 EXTU.B R0,R1 ; 番地増加分の符号無し化 |
INSLNX: MOV.L @(ENDFRE-WRKTOP,GBR),R0 ; フリーエリアの終わりの番地 MOV R3,R2 ; 現在の BASEND の値に ADD R1,R2 ; 番地増加分を足した値が CMP/HI R0,R2 ; フリーエリア最終番地より BT JOUTMEM1 ; 大きければ OUT OF MEMORY |
MOV R2,R0 ; 転送先転送開始番地=新しいBASEND MOV.L R0,@(BASEND-WRKTOP,GBR) ; をストア MOV.L R0,@(FREE-WRKTOP,GBR) ; FREE にもストア MOV.L @(GTLEN-WRKTOP,GBR),R0 ; 転送する長さ BSR LDDR ; 次の行以降を再配置 MOV R0,R1 ; 長さをR1に(遅延スロット) |
REPLNX: MOV.L @(ENTADR-WRKTOP,GBR),R0 ; 置き換えるべき行の番地を MOV R0,R2 ; R2に MOV.L @(ENTNO-WRKTOP,GBR),R0 ; 入力された行番号を MOV R0,@R2 ; 行の先頭に書き込む ADD #4,R2 ; 4バイト進める MOV.B @(ENTLEN-WRKTOP,GBR),R0 ; 入力された行の長さを EXTU.B R0,R1 ; 符号無し化して ADD #-5,R1 ; 行番号と長さバイトのぶんを引く MOV.B R1,@R2 ; 長さバイトを書き込む ADD #1,R2 ; 1バイト進める MOV.L @(GTPTR-WRKTOP,GBR),R0 ; 入力された行のテキスト部分 BSR LDIR ; テキスト部分を新しいテキストで置き換え MOV R0,R3 ; 転送元番地をR3へ(遅延スロット) BRA TOPLEV ; トップレベルに飛ぶ NOP ; (遅延スロット) |
DELLIN: BSR SCNEQL ; 同じ行番号を探す NOP ; (遅延スロット) BF JBADLIN3 ; 見つからなければエラー |
MOV R3,R2 ; 見つけた番地をR2に保存 ADD #4,R3 ; 行番号スキップ MOV.B @R3+,R1 ; 行の長さ MOV.L @(BASEND-WRKTOP,GBR),R0 ; BASICプログラムの終わり EXTU.B R1,R1 ; 長さを符号無し化 ADD R1,R3 ; 次の行の番地を計算 MOV R0,R1 ; BASEND をR1へ BSR LDIR ; 転送実行 SUB R3,R1 ; 転送する長さの計算(遅延スロット) MOV R2,R0 ; LDIR実行後のR2の値は MOV.L R0,@(BASEND-WRKTOP,GBR) ; 新しいBASENDの値 BRA TOPLEV ; 同じ値を MOV.L R0,@(FREE-WRKTOP,GBR) ; FREEにもストア(遅延スロット) |
ところで、今回あちこちに BASEND と FREE に全く同じ値を書き込んでいるところがあります。「これ、意味ないんじゃ?」と思う方もいるかもしれません。確かに現状のCCMBでは意味がないのですが、これは将来配列変数や、C言語で言うところの malloc() のような処理を実装するための布石です。 |