JH8CHUのホームページ>仮想機械>VTLによる仮想アセンブラ

VTLによる仮想アセンブラ


工事中。(2016/09/04)。
  1. 免責事項


  2. 仮想アセンブラの概要


  3. 使用方法


  4. メモリマップ

      アセンブラはVTLで記述されています。
      作業領域はVTLの配列を使用します。
      下図はVTLの配列のメモリ・マップです。


  5. データ構造

      オリジナルのマイクロ・エディタでは文字コードは7ビットであり、残りの1ビットを
      行間マークとして使用していますが、本エディタでは文字コードは8bitのASCIIコード
      そのものであり、行末には区切り文字(0x00)があるものとします。
      また、下図の例では、現在行は6行目になります。



  6. 変数の割当

      パラメータ・スタックを使用しなかったので、一部の変数を使いまわししており
      処理が少し汚くなっております。(^^;

      変数名割当機能備考
      Aファイル用作業領域の先頭(TOP) 
      Bファイル用作業領域の末尾(BOTM) 
      Cポインタ(UP) 
      Dポインタ(DN)未使用、予約
      E上部分の行数(OVER)未使用、予約
      F下部分の行数(UNDR)未使用、予約
      Gアセンブル中のソースの行 
      Hスタックポインタの初期値
      入力バッファの先頭
       
      I入力テキストのポインタ 
      Jアセンブル出力のポインタ 
      Kソースリストの行数 
      Lラベルテーブルのポインタ 
      Mラベルテーブルのエントリ数 
      Pパラメータ・スタック・ポインタ(未使用) 
      Rリターン・スタック・ポインタ 
      UサブルーチンRDSEC、WTSEC内などで使用 
      VサブルーチンRDSEC、WTSEC内などで使用 
      WサブルーチンRDSEC、WTSEC内などで使用 
      Xサブルーチン内で消費 
      Yサブルーチン内で消費 
      Zサブルーチン内で消費 

  7. 処理ルーチン一覧

    配列内の文字列のアドレスは、全てバイト・アドレスです。

    1. vasm1の処理ルーチン一覧
      行番号名称入力出力処理備考
      1000PSHR X:RSに積む値---変数Xをリターンスタックにプッシュします。
      サブルーチンの冒頭で変数!に格納されたメインルーチンへ
      の戻りアドレスをリターンスタックに積むときに使用します。
       
      1100RET ------サブルーチンからメインルーチンに戻ります。そのために
      リターンスタックに格納された戻りアドレスを変数「#」に
      代入します。
       
      2200RDSECY:読込むアドレス
      Z:セクタ番号
      --- 仮想セクタから配列に1セクタ読み込みます。  
      2400WTSECY:書込むアドレス
      Z:セクタ番号
      --- 配列から仮想セクタへ1セクタ書き込みます。  
      3000SKPSPI:文字列アドレスI:文字列アドレス 変数Iで示す文字列から、空白を読み飛ばします。  
      3100GETWDI:入力文字列アドレス I:文字列の先頭アドレス
      Y:文字列の最終アドレス+1
      入力時の変数Iのアドレスから空白、タブ、改行以外の
      文字列の検索を開始し、文字列の先頭アドレス(変数I)と
      文字列の最終アドレス(変数Y)を返します。
      文字列が無かったときは、変数I=変数Yとなります。
      入力の最終アドレスは変数Cです。
       
      3300MOVEI:移動元の文字列の先頭
      Y:移動元の文字列の最終+1
      J:移動先の先頭アドレス
      I:文字列の先頭アドレス
      Y:文字列の最終アドレス
      文字列を移動します。
       
      3500DTOBI:文字列のアドレス
      I:更新された文字列アドレス
      Z:変換した数値
      変数Iからの文字列を符号なし整数に変換し
      変数Zに返します。 数値に変換出来ない時は
      Z=0が返されます。
       
      100START------ vasm1で使用する変数を初期化します。
       


    2. vasm2の処理ルーチン一覧(作成中)
      行番号名称入力出力処理備考
      1000PSHR X:RSに積む値---変数Xをリターンスタックにプッシュします。
      サブルーチンの冒頭で変数!に格納されたメインルーチンへ
      の戻りアドレスをリターンスタックに積むときに使用します。
       
      1100RET ------サブルーチンからメインルーチンに戻ります。そのために
      リターンスタックに格納された戻りアドレスを変数「#」に
      代入します。
       
      1400ACPTG:文字列を格納する
       配列の先頭
      X:入力した文字数 キーボードから文字列を入力し、入力バッファ
      (先頭は変数G)以降の配列に格納します。
      Xに文字列末尾の0x00は含みません。
       
      1500DISP Y: 文字列のアドレス-1--- 配列に格納された文字列を画面に出力します。
      文字列の位置は変数Y+1から
      区切り文字0x00までです。
       
      1600DISP1 Y: 文字列のアドレス-1--- 配列に格納された文字列を画面に出力します。
      文字列の位置は変数Y+1から
      区切り文字0x00までです。変数Yが
      BOTM(変数B)に達しているときは何も表示しません。
       
      2000DTOBY: 文字列のアドレスZ: 変換した数値 変数Yからの文字列を符号なし整数に変換し
      変数Zに返します。数値に変換出来ないときは
      Z=0が返されます。
       
      2200RDSECY:読込むアドレス
      Z:セクタ番号
      --- 仮想セクタから配列に1セクタ読み込みます。  
      2400WTSECY:書込むアドレス
      Z:セクタ番号
      --- 配列から仮想セクタへ1セクタ書き込みます。  
      3000SKPSPI:文字列アドレスI:文字列アドレス 変数Iで示す文字列から、空白を読み飛ばします。  
      3100GETWDI:入力文字列アドレス I:文字列の先頭アドレス
      Y:文字列の最終アドレス+1
      入力時の変数Iのアドレスから空白、タブ、改行以外の
      文字列の検索を開始し、文字列の先頭アドレス(変数I)と
      文字列の最終アドレス(変数Y)を返します。
      文字列が無かったときは、変数I=変数Yとなります。
      入力の最終アドレスは変数Cです。
       
      3300MOVEI:移動元の文字列の先頭
      Y:移動元の文字列の最終+1
      J:移動先の先頭アドレス
      I:文字列の先頭アドレス
      Y:文字列の最終アドレス
      文字列を移動します。
       
      3500XASMI:文字列のアドレス
      I:更新された文字列アドレス
      Z:変換した数値
      変数Iからの16進数の文字列を符号なし整数に
      変換しテーブルに格納します。 数値に変換
      出来ない時は0が格納されます。
       
      3700XTOBI:文字列のアドレス
      I:更新された文字列アドレス
      Z:変換した数値
      変数Iからの16進数の文字列を符号なし整数
      に変換し変数Zに返します。 数値に変換
      出来ない時はZ=0が返されます。
       
      4000SRCHRI:文字列のアドレス
      Y:文字列の最終+1
      K:予約語のエントリ数
      W=1:有り、W=0:なし
      ・W=1のとき
      X:予約語のコード
      Z:予約語の属性
      ソースから分離した文字列が予約語にあるか
      検索します。
       
      4300SRCHLI:文字列のアドレス
      Y:文字列の最終+1
      L:ラベルのアドレス
      X:ラベルのアドレス ラベルがラベルテーブルにあるか
      検索します。
      ラベルがテーブルにないときは、エラー・メッセージ
      を表示してアセンブラを終了します。
       
      5000PIFFJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      Sは2小さくなり、下記の
      値がスタックに
      格納される。
      (S):ペアチェックの
      初期値で2となる。
      (S+1):0branch命令の
      格納アドレス
      疑似命令ifの処理をするサブルーチンです。
      疑似名whileでも使用されます。
      データ・スタックに格納される出力値の詳細は
      疑似命令if、whileを参照してください。
       
      5200PAGNJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      入力はデータ・スタック
      に格納します。
      (S):ペアチェックの
      値で1。
      (S+1):branch命令の
      格納アドレス
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      Sの値は2小さくなる。
      疑似命令againの処理をするサブルーチンです。
      疑似名repeatでも使用されます。
      データ・スタックに格納される入力値の詳細は
      疑似命令のagain、repeatを参照してください。
       
      5400PEDIFJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      入力はデータ・スタック
      に格納します。
      (S):ペアチェックの値で2。
      (S+1):branch命令の
      格納アドレス
      J:アセンブル出力の
      ポインタ。Jは不変。
      S:Sの値は2大きくなる
      疑似命令endifの処理をするサブルーチンです。
      疑似名repeatでも使用されます。
      データ・スタックに格納される入力値の詳細は
      疑似命令のendif、repeatを参照してください。
       
      11600LITJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      疑似命令litの処理です。
       
      13200BSRJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは3進む。
      疑似命令bsrの処理です。
       
      13400DOJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      J:アセンブル出力の
      ポインタ。Jは1進む。
      Sは2小さくなり、
      下記の値がスタック
      に格納される。
      (S):ペアチェックの
      初期値で3となる。
      (S+1):do命令の
      次のアドレス
      疑似命令doの処理です。
       
      13500LOOPJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      (S):ペアチェックの
      初期値で3。
      (S+1):do命令の
      次のアドレス
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      S:データ・スタック
      のポインタ
      Sは2大きくなる
      疑似命令loopの処理です。
       
      13600PLOOPJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      (S):ペアチェックの
      初期値で3。
      (S+1):do命令の
      次のアドレス
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      Sは2大きくなる
      疑似命令+loopの処理です。
       
      13700BEGINJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      J:アセンブル出力の
      ポインタ。Jは不変。
      Sは2小さくなり、
      下記の値がスタック
      に格納される。
      (S):ペアチェックの
      初期値で1となる。
      (S+1):ループ処理
      の開始アドレス
      疑似命令beginの処理です。
       
      13800UNTILJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      (S):ペアチェックの
      初期値で1
      (S+1):ループ処理
      の開始アドレス
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      S:データ・スタック
      のポインタ
      ループ継続時:Sは不変
      ループ終了時:Sは2
      大きくなる
      疑似命令unitlの処理です。
       
      13900WHILEJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      Sは2小さくなり、下記の
      値がスタックに
      格納される。
      (S):ペアチェックの
      初期値で2となる。
      (S+1):0branch命令の
      格納アドレス
      疑似命令whileの処理をするサブルーチンです。  
      14000REPEAJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      入力はデータ・スタック
      に格納します。
      (S):ペアチェックの値で2。
      (S+1):ループ処理
      の開始アドレス
      (S+2):ペアチェック
      の値で3。
      (S+3):branch命令の
      格納アドレス
      J:アセンブル出力の
      ポインタ。Jは不変。
      S:Sの値は4大きくなる
      疑似命令repeatの処理です。  
      14100IFFJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      のポインタ
      J:アセンブル出力の
      ポインタ。Jは3進む。
      Sは2小さくなり、下記の
      値がスタックに
      格納される。
      (S):ペアチェックの
      初期値で2となる。
      (S+1):0branch命令の
      格納アドレス
      疑似命令ifの処理です。
      サブルーチンPIFFを呼ぶだけです。
       
      14200ELSEJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      入力はデータ・スタック
      に格納します。
      (S):ペアチェックの値で2。
      (S+1):0branch命令の
      格納アドレス
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      Sの値は不変。
      (S):ペアチェックの値で2。
      (S+1):branch命令の
      格納アドレス
      疑似命令elseの処理です。  
      14300ENDIFJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      入力はデータ・スタック
      に格納します。
      (S):ペアチェックの値で2。
      (S+1):branch命令の
      格納アドレス
      J:アセンブル出力の
      ポインタ。Jは不変。
      S:Sの値は2大きくなる
      疑似命令endifの処理です。
      サブルーチンPEDIFを呼ぶだけです。
       
      14400AGAINJ:アセンブル出力の
      ポインタ
      S:データ・スタック
      入力はデータ・スタック
      に格納します。
      (S):ペアチェックの値。
      (S+1):branch命令の
      格納アドレス
      J:アセンブル出力の
      ポインタ
      Jは3進む。
      Sの値は2小さくなる。
      疑似命令againの処理です。
      サブルーチンのPAGNを呼ぶだけです。
       
      34000DBJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは1進む。
      疑似命令dbの処理です。  
      34100DWJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは2進む。
      疑似命令dwの処理です。  
      34300FCAJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは2進む。
      疑似命令fcaの処理です。
       
      34400PFAJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは2進む。
      疑似命令$+2の処理です。
       
      34500LITDAJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは3進む。
      疑似命令lit.aの処理です。
       
      35300ENDJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは2進む。
      疑似命令endの処理です。  
      35400LABELJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ。Jは3進む。
      疑似命令labelの処理です。  
      40000NEXTJ:アセンブル出力の
      ポインタ
      J:アセンブル出力の
      ポインタ
      疑似命令の終わりの処理です。
      この行では特に何もせず、
      次のアセンブル処理に分岐するだけです。
       
      100START------ vasm1で使用する変数を初期化します。
       

  8. 処理詳細

    1. PSHR
      (1)機能
      行番号名称入力出力処理備考
      1000PSHR X:RSに積む値---変数Xをリターンスタックにプッシュします。
      サブルーチンの冒頭で変数!に格納されたメインルーチンへ
      の戻りアドレスをリターンスタックに積むときに使用します。
       

      (2)処理内容
        VTLではサブルーチンがメインルーチンに戻る際に必要となる戻りアドレスが
        変数!に格納されていますが、変数!が破壊されてもよいようにサブルーチンの
        冒頭で戻りアドレスをリターン・スタックに格納するために使用します。
        本ルーチンを呼び出すことにより変数!が破壊されてしまうため
        戻りアドレスは変数Xに格納してから、本ルーチンを呼び出します。
        なお本ルーチンを使用したときは、サブルーチンから戻るときに、 RETを使用します。

      (3)ソース・リスト
        1000 R=R-1
        1010 :R)=X
        1020 #=!

        [解説]
        1000 リターン・スタックのポインタをデクリメント
        1010 変数X(戻り行番号)をリターン・スタックに格納
        1020 このルーチンを呼び出したサブルーチンに戻る

    2. RET
      (1)機能
      行番号名称入力出力処理備考
      1100RET ------サブルーチンからメインルーチンに戻ります。そのために
      リターンスタックに格納された戻りアドレスを変数「#」に
      代入します。
       

      (2)処理内容
        PSHRルーチンを呼び出して戻りアドレスを リターン・スタックに
        格納したサブルーチンがメイン・ルーチンに戻るときに使用します。
        そのために、リターンスタックに格納された戻りアドレスを
        変数「#」に代入します。

      (3)ソース・リスト
        1100 !=:R)
        1110 R=R+1
        1120 #=!

        [解説]
        1100 リターン・スタックに積まれたメイン・ルーチンの戻り行番号を変数!に戻す。
        1110 リターン・スタックのポインタをデクリメント
        1120 メイン・ルーチンにジャンプ

    3. ACPT
      (1)機能
      行番号名称入力出力処理備考
      1400ACPTG:文字列を格納する
       配列の先頭
      X:入力した文字数 キーボードから文字列を入力し、入力バッファ
      (先頭は変数G)以降の配列に格納します。
      Xに文字列末尾の0x00は含みません。
       

      (2)処理内容
        キーボードから文字列を入力し配列に格納します。
        配列の先頭アドレスは変数Gで指定します。
        なお、配列のアドレスはバイト・アドレスになります。
        入力された文字列の終わりに文字列の終わりを示す(区切り文字)
        0x00が追加されます。
        戻り値として変数Xに入力された文字列の文字数が設定されます。
        Xの文字数には区切り文字は含みません。
        (空行入力時はX=0です)

      (3)ソース・リスト
        1400 ^=G
        1410 X=$
        1420 #=!

        [解説]
        1400 文字列を格納する配列のポインタを設定。(変数^はVTLの変数)
        1410 文字列を入力し、入力文字数を変数Xに格納。(変数$はVTLの変数)
        1420 このルーチンを呼び出したサブルーチンに戻る

    4. DISP
      (1)機能
      行番号名称入力出力処理備考
      1500DISP Y: 文字列のアドレス-1--- 配列に格納された文字列を画面に出力します。
      文字列の位置は変数Y+1から
      区切り文字0x00までです。
       

      (2)処理内容
        配列に格納された文字列を画面に出力します。
        表示する文字列の先頭は変数Yで指定しますが、
        実際に表示される文字列の位置はY+1からです。
        文字列の終わりには区切り文字(0x00)が必要です。
        なお、配列のアドレスはバイト・アドレスになります。

      (3)ソース・リスト
        1500 X=!
        1510 #=1000
        1520 ^=Y+1
        1530 #=(\=0)*1570
        1540 $=\
        1550 Y=Y+1
        1560 #=1520
        1570 ?=""
        1580 #=1100

        [解説]
        1500 戻り行番号を
        1510 リターン・スタックに積む。
        1520 表示文字のある配列のバイト・アドレスを、バイト・アクセスのポインタに設定。
        1530 文字が区切り文字なら表示終了。
        1540 ポインタの位置の文字を1文字表示。
        1550 ポインタをひとつ進める。
        1560 文字列表示のためのループ。
        1570 改行を表示して、
        1580 メイン・ルーチンに戻る。

    5. DISP1
      (1)機能
      行番号名称入力出力処理備考
      1600DISP1 配列に格納された文字列を画面に出力します。
      文字列の位置は変数Y+1から
      区切り文字0x00までです。変数Yが
      BOTM(変数B)に達しているときは何も表示しません。
       

      (2)処理内容
        配列に格納された文字列を画面に出力します。
        表示する文字列の先頭は変数Yで指定しますが、
        実際に表示される文字列の位置はY+1からです。
        文字列の終わりには区切り文字(0x00)が必要です。
        ポインタ(変数Y)がファイル用作業領域の末尾(BOTM)に
        達している場合はポインタは移動せず、「(EOT)」と表示して、
        メイン・ルーチンに戻ります(EOTの表示はオリジナルにはありません)。
        なお、配列のアドレスはバイト・アドレスになります。

      (3)ソース・リスト
        1600 X=!
        1610 #=1000
        1620 #=(Y>B)*1650
        1630 #=1500
        1640 #=1100
        1650 ?="(EOF)"
        1660 #=1100

        [解説]
        1600 戻り行番号を
        1610 リターン・スタックに積む。
        1620 表示する文字列のポインタがBOTM(変数B)に達したらポインタは移動しない。
        1630 ポインタ(変数Y)の位置の文字列を表示する。
        1640 メイン・ルーチンに戻る。
        1650 テキストの終わりであること(EOT)を表示する。
        1660 メイン・ルーチンに戻る。

    6. DTOB
      (1)機能
      行番号名称入力出力処理備考
      2000DTOBY: 文字列のアドレスZ: 変換した数値 変数Yからの文字列を符号なし整数に変換し
      変数Zに返します。数値に変換出来ないときは
      Z=0が返されます。
       

      (2)処理内容
        文字列を数値に変換します。
        変換は、最初に数値以外の文字が現れるまで続けらます。


      (3)ソース・リスト
        2000 X=!
        2010 #=1000
        2020 Z=0
        2030 ^=Y
        2040 X=\-48
        2050 #=(X<9)*2080
        2070 #=1100
        2080 Z=Z*10+X
        2090 Y=Y+1
        2100 #=2030

        [解説]
        2000 戻り行番号を
        2010 リターン・スタックに積む。
        2020 結果を格納する変数Zをクリア。
        2030 文字列のポインタをVTLの変数^に格納し、
        2040 その位置の文字(バイト)が48("0")〜57("9")なら、
        2050 その文字は数字である。
        2060 (削除)
        2070 数字以外の文字があれば変換終了。
        2080 変換済の数値は桁上げし、次の数値を変換済の数値に足す。
        2090 文字列のポインタを更新し、
        2100 変換のループを回る。

    7. RDSEC
      2200RDSECY:読込むアドレス
      Z:セクタ番号
      --- 仮想セクタから1セクタ配列に読み込みます。  

      (2)処理内容
        変数Zで示される仮想セクタから、1セクタのデータを読み込み
        変数Yで示される配列のアドレスに格納します。

      (3)ソース・リスト

        [解説]

    8. LOAD

      (2)処理内容

      (3)ソース・リスト

        [解説]

    9. CHNG

      (2)処理内容

      (3)ソース・リスト

        [解説]

    10. START
      行番号名称入力出力処理備考
      100START------ エディタで使用する変数を初期化して
      エディタを開始します。
       

      (2)処理内容
        アセンブラで使用する定数・変数を初期化します。
        変数AとBの設定値はまだ暫定です。

      (3)ソース・リスト

        [解説]

        9000 スタック・ポインタを初期化します。
        9010 マイクロ・エディタの開始のメッセージです。オリジナルにはありません。
           この後、10000行からエディタの処理に接続します。



JH8CHUのホームページ>仮想機械>VTLによる仮想アセンブラ


Copyright (C)2016 Masahiro.Matsuda(JH8CHU), all rights reserved.