﻿==============================================================================
■はじめに

  ・8080,8085,Z80 のクロス開発を想定した(アブソリュート)アセンブラです
  ・インテル, ザイログの両ニモニックに対応しています
    Ver. 0.7.0 から SC/MP に仮対応しています
    Ver. 0.8.0 から MC6800 に仮対応しています
  ・エミュレータ(j80, u80, c80, m80, j68)に組み込むためのモードを備えています
  ・ZASM(v1.64) に似たログを出力します

  ・出力フォーマットは、tools80 のドキュメントを参照してください
    具体的な使い方は、各エミュレータ, tools80 のドキュメントを参照してください

  ・ZASM(v1.64) の仕様を参考にさせていただきました
    http://www.vector.co.jp/soft/dos/prog/se010314.html

  ※暫定版です
  ・使用してはいけないアドレス範囲を定義できるようにする？
  ・エラーメッセージを丁寧にしたい


==============================================================================
■オブジェクトの配置
  ・バイナリ生成済みのアドレスは上書きできません
  ・バイナリが生成されなかったアドレスの内容はオブジェクトに含まれません


==============================================================================
■ソース・ファイル
  ・デフォルトの文字コードは「Windows-31J」です
    先頭行に 文字セット名(またはコンバータ名) をコメントアウトして指定できます
    INCLUDEするファイル毎に独立した指定が可能です
    ※BOM付き UTF に対応しました (2022.08.27)
      BOM付きの場合は *encoding指定を無視します
    ※ソースの指定に拠らず logファイルの文字コードは「UTF-8」になります
    [参考 (Shift-JIS系)]
        [文字セット]     [コンバータ]
        Windows-31J      MS932
        Shift_JIS        MS932      (J2SE1.2～1.4.1b以前)
        Shift_JIS        SJIS       (J2SE1.4.1b～)
  ・同一行に複数のオペコード,擬似命令を記述できません(マルチステートメント不可)
  ・一部の擬似命令を除き、行頭にラベルを記述(追加)することができます
    ・行頭にラベルを記述できない擬似命令等とその理由：
      ・ラベル
        マクロの呼び出しミス等、記述ミスの可能性が高いのでエラーとしています
      ・ORG, EQU
        ログのアドレス部にはラベルの値が表示されます
        シンボル定義行ではシンボルの値と勘違いしがちなので制限しました
  ・カラムの区切り文字は
      オペコード(予約語,シンボル,ラベルを含む) は 空白, タブ
      オペランド(各種引数を含む) は カンマ
    です
    引用符や括弧の中の区切り文字は無視します
    ※「AF'」のアポストロフィを引用符と誤認するバグが出たら報告をお願いします
    オペコード と オペランドの間には一文字以上の 空白 または タブ が必要です
    コロンは区切り文字としませんが、ラベル末尾のコロン(:)の後ろは区切り文字は
    不用としています
  ・セミコロン(;) 以降はコメントとして扱います
    但し、引用符の中のセミコロンは無視します
  ・行の冒頭にアスタリスク(*),スラッシュ(/)がある場合はその行をコメントとします
    ラベルに続いてアスタリスク,スラッシュがある場合はそれ以降をコメントとします
    この形式のコメントは、行の冒頭,ラベルの後ろ以外には置けません
   「*」で始まるコメント行は「ドキュメント」あるいは「見出し」とします
    ログにはダンプ部分の字下げなしで出力されます
  ・式はスペース,タブで分かち書きが可能です
    ※Zilog表記の (レジスタ), (IX ... ), (IY ... ) の括弧は式ではありません
      n, lm と (n), (lm) は、式全体が括弧で囲まれているか否かで区別しています
      不要な括弧はつけないでください
  ・内容が "" となるカンマ切りの要素は 0 とします
     , , は 0,0,0 になります
    データ末尾のカンマの後ろにも 0 が補われますので注意してください


==============================================================================
■ロケーション・カウンタ
  ・ロケーション・カウンタは 0x0000 -> 0xFFFF を循環します
    SC/MP でも同様です
    ※出力済みのアドレスを上書きしようとした際にはエラーとなります
  ・ロケーション・カウンタは ソースファイルの「行」単位に更新します
    マクロで展開された場合も展開後の「行」を基準に推移します
  ・特殊なシンボル「$」でアクセスできます
    MC6800 のアセンブラで「*」でアクセスするものがありますが使えません

==============================================================================
■式
  ・評価中は 符号付き32bit の整数で処理します
  ・特記なき場合、0xFFFF でマスクされた値が返ります
  ・空白, TAB で分かち書きが可能です

------------------------------------------------------------------------------
  □演算子
  ~~~~~~~~~~~~~~~~~~~~
    (   )           : 右    
    ~   !           : 右   「!」: FALSE(0) ⇔ TRUE(0以外 / 演算結果は 0xFF)
    *   /   %       : 左    
    +   -           : 左   「+」: 文字列が含まれる場合「連結」  <文字列対応>
    <<  >>          : 左    算術シフト(内部計算のみ32bit符号付き)
    <   <=  >   >=  : 左    非結合ではありません
    ==  !=          : 左    非結合ではありません                <文字列対応>
    &               : 左   「&」: 文字列が含まれる場合「連結」  <文字列対応>
    ^               : 左    XOR
    |   !           : 左   「!」: 二項演算子の場合は OR とみなす
    &&              : 左    短絡評価します (評価対象外の式も構文解析は行います)
    ||              : 左    短絡評価します (評価対象外の式も構文解析は行います)
    ?   :           : 右    短絡評価します (評価対象外の式も構文解析は行います)


  □定数
  ~~~~~~~~~~~~~~~~~~~~
  ・下記条件に当てはまるものを数値として評価します
    ・先頭が数字で始まる														...先頭が数字または「_」で始まる	とするか？
      ・「2001B」は数値として評価しますがエラーとなります
    ・先頭が「$」で、先頭の桁が「数字」または「A」-「F」
      ・「$_123」は数値として評価しません										...検討中「$_」を 00H として良いか？？？
    ・先頭が「@」で、先頭の桁が「0」-「7」
      ・「@_123」は数値として評価しません										...検討中「@_」を 00Q として良いか？？？
    ・「%」が式の冒頭にあるか「)」以外の演算子に続き、先頭の桁が「0」または「1」
      ・「%2001」は数値として評価しません
      ・「%1002」は数値として評価しますがエラーとなります
    ※これら「数値として評価対象となる文字列」はエラーとなるケースも含め
      ラベル等に使用できません
  ・フォーマット (英文字は小文字も受け付けます)
    ・16進数：「...H」または「$...」または「0X...」または「X'...'」
    ・ 8進数：「...O」または「@...」または「0O...」または「...Q」
    ・ 2進数：「0X... でなく ...B」または「...H でなく 0B...」
    ・10進数：「0X... でなく ...D」または 数字(識別子なし)
  ・実数は使用できません
  ・定数は 0xFFFF でマスクした16bit値が返ります
    bit15 は符号ではありません (右シフトに注意)
  ・先頭を除く任意の場所に「_」を挿入して分かち書きが可能です


  □文字定数
  □文字列
  ~~~~~~~~~~~~~~~~~~~~
  ・「'」または「"」で囲まれたもののうち
    ・一文字のものを「文字定数」
    ・それ以外を「文字列」
    とします

    文字定数の例：
      'A', '"', "'"

    文字列の例：
      'ABC', '"YES"'
      "" (長さ0の文字列)
      ""&0 の評価結果 (長さ1の文字列)
      "GAME OVER"&0 の評価結果

  ・エスケープ処理には対応していません
  ・文字列は連結(「+」,「&」) 比較(「==」,「!=」) が可能です
    演算子の少なくとも片方が文字列の場合、文字列の演算となります
   「長さ0の文字列」と連結した数値(文字定数を含む)は「文字列」になります
    比較演算の結果は数値となります
  ・文字は 0x00-0xFF の「キャラクタコード」として演算します
    キャラクタコードはソースコードのエンコーディングに依存しません
    ソースコードを UTF-16 に変換して 0x00-0xFF のコードはそのまま、
    0x100以上の場合は内部のマップに従いキャラクタコードに変換します
    マップに含まれない文字は使用できません
    使用できない文字は値として評価する際にエラーとなります

    文字の演算の例：
      'ア:U+30A2'+1 ＝ 'ィ:U+30A2' ⇒ 'ｨ:$A8' ではなく
      'ア:U+30A2'+1 ⇒ 'ｱ:$B1'+1 ＝ 'ｲ:$B2 になります

    文字列の演算の例：      (Ⅱ：使用できない文字)
      "PC-8001mk"&'Ⅱ'&0    演算(結合)時にエラーとなる
      "PC-8001mkⅡ"&0       演算(結合)時にはエラーとならない
      IF arg=="PC-8801mkⅡ" 比較では文字として評価しないのでエラーにならない


  □シンボル
  ~~~~~~~~~~~~~~~~~~~~
  ・後述


==============================================================================
■ファイル名
  ・ファイル名は相対パスで記述できます
    パスの区切り文字は、プラットフォームによらず「/」が使用できます
  ・式(文字列)として処理しますので「"」または「'」で囲んでください


==============================================================================
■擬似命令
  ・余分な引数があってもエラーとしません
  ・擬似命令の予約語は大文字/小文字を区別しません


------------------------------------------------------------------------------
  □シンボル名 EQU 式
  □シンボル名  =  式
  ~~~~~~~~~~~~~~~~~~~~
  ・シンボルを定義します
    オペレーションカウンタは更新しません
    ラベルと同じ行では定義できません (logの見やすさ優先)
  ・末尾に「:」を付けたシンボルは「アドレス型」として区別します
    「アドレス型」の値は相対アドレスの計算対象となる場合があります
  ・末尾の「:」はシンボル名に含めません
  ・シンボル名は大文字/小文字を区別します
  ・シンボル名の制限
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・シンボルは再定義できません
    但し、同じ型,値で再定義された場合はエラーとしません
  ・シンボル名はラベルと同じ管理ですので重複できません
    マクロ名とは別管理ですので重複可能です
  ・「$」はオペレーションカウンタをあらわす特別なシンボルとして定義済みです
    「$」は相対アドレスの計算対象となる場合があります
  ・シンボルの値に文字列は定義できません
  ・ローカル および テンポラリ・シンボルが使用できます
    定義時に「現在のPREFIX(名前空間)」を更新しない点を除いてラベルと同じです
    詳細は「ラベル」の項を参照してください
  ・式が 1PASS目に解決できなかった場合はエラーとします


  □IF 式
    IFDEF シンボル名
    IFNDEF シンボル名
  □ELSEIF 式
  □ELSE
  □ENDIF
  ~~~~~~~~~~~~~~~~~~~~
  ・0:FALSE / 0以外:TRUE
  ・式が FALSE の場合、その節をスキップします
  ・式!FALSE の場合、次の節まで処理を進めます
    次の節が ELSEIF だった場合、ENDIF までスキップします
  ・スキップした行は、ログの先頭に ";;" と "-" を付けて出力します
  ・ネスト可能です
  ・式が 1PASS目に解決できなかった場合はエラーとします
    ※式にエラーがあった場合、対応する ENDIF までスキップします
      通しでログを出力したいので誤魔化しながら 1PASS目の完走を目指します
      エラー以降のアドレスは信頼できませんので注意してください
  ・スキップされる節中の INCLUDE, CHAIN, 各種マクロは展開されません


  □REPT 式
  □ENDM
  ~~~~~~~~~~~~~~~~~~~~
  ・対応する ENDM までを 式の回数繰り返します (ループマクロ)
  ・式が 1PASS目に解決できなかった場合はエラーとします
    解決後の値(繰り返し回数/符号付32bit)が渡されます
  ・ループ回数が 0以下だった場合は何もしません
    ループ回数が 0xFFFF回を超える場合は処理を行わずにエラーとします
  ・ループマクロ中では「ローカル・ラベル」が展開されます
  ・ネスト可能です


  □IRP 仮引数 , 実引数 [, 実引数 [, ...]]
  □ENDM
  ~~~~~~~~~~~~~~~~~~~~
  ・対応する ENDM までを (引数の数)回繰り返します (ループマクロ)
  ・仮引数(名)の制限
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・実引数は「そのまま」渡されます
    渡す相手によって、引数の表現を調整する必要があります

    IRP var,"A","B","C","D","E"
      DB var
    ENDM

    IRP var,B,C,D,E,(HL),A
      LD A,var
    ENDM

  ・ループマクロ中では「ローカルラベル」が展開されます
  ・ネスト可能です


  □IRPC 仮引数 , 実引数(文字列)
  □ENDM
  ~~~~~~~~~~~~~~~~~~~~
  ・対応する ENDM までを (文字列の長さ)回繰り返します (ループマクロ)
  ・実引数は評価後に文字定数の値(数字)がマクロに渡されます
    1PASS目に解決できなかった場合はエラーとします
  ・仮引数(名)の制限
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・実引数は評価後、文字に分割して渡されます
  ・ループマクロ中では「ローカルラベル」が展開されます
  ・ネスト可能です


  □マクロ名 MACRO [仮引数 [, ...]]
  □ENDM
  ~~~~~~~~~~~~~~~~~~~~
  ・マクロを定義します
  ・マクロ定義はネストできますがあまり意味が無いのでお勧めしません
    子マクロ中の文字列も親による置換対象になります
  ・マクロ定義にマクロの呼び出しやループマクロを含めることができますが、
    循環チェックしていませんので注意してください
  ・マクロ名の制限
    ・「IF, ELSEIF, ELSE, ENDIF, REPT, IRP, IRPC, ENDM」は使用できません
    ・「.」で始まる文字列は使用できません
    ・末尾が「:」の名前は使用できません
    ※現在は下記文字列も使用できますが、将来制限するかもしれません
      ・「数値として評価対象となる文字列」
      ・演算子として使用する文字を含む文字列
      ・「"」,「'」を含む文字列
  ・マクロ名は再定義できません (仮引数の件数によるオーバーロードは認めます)
    通常のシンボル(ラベル)と重複する名前も使用できますが、動作は保証しません
  ・マクロ名にオペコードや禁止されていない擬似命令を使用し操作を上書きできます
    但し、マクロ名は大文字/小文字を区別しますので注意してください
  ・マクロ名は「テンポラリ・ラベル」と同じ書式により「マクロID」で修飾できます
  ・仮引数は最大 16件 で、重複してはいけません
  ・仮引数(名)の制限
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・仮引数が使われている場所は、次のロジックで特定します
      1. 行を、区切り文字, 演算子に含まれる文字で分割する
         分割に用いる文字は検索対象に含みません
         文字列(型)の文字列には「"」「'」も含まれます
      2. 分割された文字列が仮引数と同じか確認する
         対象が文字列(型)だった場合は、文字列の内容が完全に一致した場合のみ
         仮引数とします
         それ以外の文字列(型)中の仮引数と一致する部分は無視します

      DB MACRO a, op, b   ; 
           db a op b      ; ※分かち書きすること (aopb は分割されない)
           endm           ;

      XOR MACRO reg       ;
           if "reg"=="A"  ; reg は実引数に置換され、文字列として評価されます
                          ; 例：XOR A → "A"=="A" (true)
                          ; 例：XOR B → "B"=="A" (false)
              LD reg,0    ; XOR A → LD A,0
           else           ;
              xor reg     ; XOR B → xor B
           endif          ;
           endm           ;

  ・仮引数の先頭に「*」を付けた場合は、ひとつ以上の実引数を受け付けます
   「*」は仮引数の名前には含まれません
   「*」による指定が複数あった場合はエラーとします

      DO MACRO key, *args, note
         DB  key
         IRP arg, args
         DB  "1.",arg
         ENDM
         DB  note
         ENDM

      DO "PC-8001mkIISR", "6",         "24K"
      DO "PC-8001mkII",   "2",         "24K"
      DO "PC-8001",       "0","1",     "24K"
      DO "PC-8801",       "4","5","8", "32K"

  ・仮引数に未使用のものがあってもエラー, 警告を出しません
  ・実引数は「そのまま」渡されます


  □マクロ名 [実引数 [, ...]]
  ~~~~~~~~~~~~~~~~~~~~
  ・マクロ名は大文字/小文字を区別します
  ・名前と引数の数が一致して下記条件に当たらない場合、マクロとして展開します
      ・名前末尾が「:」                               (→ ラベル定義)
      ・引数があり、最初のものを大文字に揃えて「EQU」 (→ シンボル定義)
      ・引数があり、最初のものが「=」                 (→ シンボル定義)
    一致するものがない場合、ここではエラーとしません
      SUB MACRO regA,src
          SUB src
      ENDM
    「SUB A,(HL)」はマクロが「SUB (HL)」に置換してから再評価される
    「SUB (HL)」は引数の数が一致しないのでそのままアセンブラに渡される

  ・「$」は展開後に各行を評価するときの値になります

  ・引数は、文字列そのものを渡します (展開時には評価しません)
    式に挿入される場合、評価順に注意してください

      sample1 MACRO param
        LD A, param*10
      ENDM
      sample1 1+2   → LD A, 1+2*10
      sample1 (1+2) → LD A, (1+2)*10

      sample2 MACRO param
        LD A, (param)*10
      ENDM
      sample2 1+2   → LD A, (1+2)*10
      sample2 (1+2) → LD A, ((1+2))*10 ※無駄な括弧は悪影響ありません

  ・循環チェックしていませんので注意してください
      LD MACRO reg, val
      ;  LD reg,val&7FH   ; 無限ループって怖くね？
         ld reg,val&7FH   ; OK
      ENDM


  □関数名 FUNCTION [仮引数 , [... ,]] 式
  ~~~~~~~~~~~~~~~~~~~~
  ・式の中で「関数名 ( [仮引数 , [... ,]] )」の形で使用します
    例：
      H FUNCTION v16, v16 >> 8;
      LDI H(SCORE); → LDI SCORE >> 8
  ・関数名は大文字/小文字を区別します
  ・関数名の制限
    ・「.」で始まる名前は使用できません
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・仮引数(名)の制限
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・引数は「式」として評価した値が渡されます
    マクロの引数とは扱いが違いますので注意してください
  ・関数の処理内容はログに出力されません
  ・再帰呼出しに対応しています
    例：
      sum FUNCTION i, j, (i<j)?(i+sum(i+1,j)):i
      pow FUNCTION i, j, (j>0)?(i*pow(i,j-1)):1


  □ORG 式
  ~~~~~~~~~~~~~~~~~~~~
  ・オペレーションカウンタに値(アドレス)を設定します
    ラベルと同じ行では定義できません (logの見やすさ優先)
  ・式(符号付32bit)が 1PASS目に解決できなかった場合はエラーとします
  ・式の値が負だった場合はエラーとします
    アドレスが 0xFFFFを超える場合は 16bitにマスクします
  ・何度でも設定可能です


  □END [式(エラーメッセージ)]
  ~~~~~~~~~~~~~~~~~~~~
  ・ソースに END の宣言がなくても、エラー,警告は出しません
  ・END以降のソースを *そのファイルの末尾まで* スキップします
    マクロ中の END は、呼び出したファイルの末尾までスキップします
  ・式がない場合, 式が 0 を返す場合は「正常終了」とし、[EOF]までスキップします
    スキップした行は、ログの先頭に ";;" を付けて出力します
    INCLUDE, CHAIN から戻った場合は END によるスキップは解除されます
  ・式が文字列または 0 以外の値を返す場合,式が異常の場合は「異常終了」とします
    異常終了時はその行で処理を中止します


  □CHAIN 式(ファイル名)
  ~~~~~~~~~~~~~~~~~~~~
  ・CHAIN先から戻った後、[EOF]までスキップします
   「CHAIN先から戻らない」のではないので注意してください
    [file1]========[INCLUDE file2]                    |========[EOF]
             [file2]========[CHAIN file3]    |--------[EOF]
                      [file3]================[EOF]
  ・式が1PASS目に解決できなかった場合,文字列を返さなかった場合はエラーとします
  ・スキップした行は、ログの先頭に ";;" を付けて出力します
  ・ネスト可能ですが、循環チェックをしていませんので注意してください
  ・マクロ中での動作は保障しません
  ・IF,ELSEIF,ELSE でマスクされる節では CHAIN命令そのものが無視されます


  □INCLUDE 式(ファイル名)
  ~~~~~~~~~~~~~~~~~~~~
  ・INCLUDE先から戻った後、処理を続けます
    INCLUDEファイル中の END の影響は
  ・式が1PASS目に解決できなかった場合,文字列を返さなかった場合はエラーとします
  ・ネスト可能ですが、循環チェックをしていませんので注意してください
  ・IF,ELSEIF,ELSE でマスクされる節では INCLUDE命令そのものが無視されます
    この仕様は非対称で気に入らないので、将来変更する可能性があります
    現在の動作に依存したトリックを使わないでください
        IF <false>                             IF <true>
       +INCLUDE <file>  -  -  -  -  - +       +INCLUDE <file>  -  -  -  -  - +
       :  + -  -  -  -  -  -  -  - +  :       :  +------------------------+  :
       :  :                        :  :       :  |   このブロックは有効   |  :
       :  + -  -  -  -  -  -  -  - +  :       :  +------------------------+  :
       :else                          :       :else                          :
       :  + -  -  -  -  -  -  -  - +  :       :  + -  -  -  -  -  -  -  - +  :
       :  :   このブロックも無効   :  :       :  :   このブロックは無効   :  :
       :  + -  -  -  -  -  -  -  - +  :       :  + -  -  -  -  -  -  -  - +  :
       + -  -  -  -  -  -  -  -  -  - +       + -  -  -  -  -  -  -  -  -  - +
        ENDIF                                  ENDIF                          
       ※INCLUDE命令自体がなかったことになる


  □BINCLUDE 式(ファイル名) [, 式(offset) [, 式(サイズ/末尾からのoffset)]]
  ~~~~~~~~~~~~~~~~~~~~
  ・オペレーションカウンタの位置からバイナリファイルを読み込みます
  ・式(ファイル名)
    1PASS目に解決できなかった場合,文字列を返さなかった場合はエラーとします
  ・式(offset → 読み込み開始位置)
    省略した場合は 0 となります
    1PASS目に解決できなかった場合はエラーとします
    負の値の場合はファイル末尾から先頭に向かってのオフセットになります
    読み込み開始位置がファイル先頭より前になった場合はエラーとします
  ・式(サイズ/末尾からのoffset → 読み込み終了位置)
    省略した場合はファイル末尾までとなります
    1PASS目に解決できなかった場合はエラーとします
    0以下 の場合はファイル末尾からのオフセットとします
  ・読み込みサイズが 0byte以下だった場合はエラーとします
  ・読み込み中にファイルサイズを超えてもエラーとしません
    EOF以降は 0xFF になります
  ・ログには読み込んだファイルの内容を一部のみ記録します
    省略があった場合はそのサイズを表示します


  □SYMBOL 式(ファイル名)
  ~~~~~~~~~~~~~~~~~~~~
  ・シンボルテーブルを引用します
    tools80 から実行した場合は「-debug -sym」でシンボルファイルを出力します


  □DEFS 式 [,式]
  □DS   式 [,式]
  □RMB  式 [,式]
  ~~~~~~~~~~~~~~~~~~~~
  ・オペレーションカウンタを進めます
  ・第一パラメータ
    ・スキップするバイト数
    ・式(符号付32bit)が 1PASS目に解決できなかった場合はエラーとします
    ・式の値が負だった場合は(その場所が空き地であっても)エラーとします
      スキップ中にアドレスが 0xFFFFを超えた場合は 16bitにマスクして続行します
  ・第二パラメータ
    ・第二パラメータが指定されてた場合はその値で埋めます (バイナリ生成)
    ・生成しない場合、その範囲は「予約」となります (現在の仕様では「未使用」と同じ)
      例：
        INCLUDE "work.asm"  ; ワークエリアを DS で予約
        ORG work.top        ; ↓ワークの先頭に配置して省メモリ化
        INCLUDE "init.asm"  ; 起動直後に一度しか使わないルーチン (起動後に潰される)
    ・埋めデータを生成するタイプのアセンブラ向けのソースをそのまま用いる場合は、
      マクロで DS をオーバーライドしてください
      例：
        DS MACRO off
           ds off,0   ; ※小文字 ds はオーバーライド対象にならない
        ;  DEFS off,0 ; ※普段 DEFS を使わない方向け
        ENDM


  □DEFB 式 [,式 [, ...]]
  □DB   式 [,式 [, ...]]
  □FCB  式 [,式 [, ...]]
  □DEFM 式 [,式 [, ...]]
  □DM   式 [,式 [, ...]]
  □FCC  式 [,式 [, ...]]
  ~~~~~~~~~~~~~~~~~~~~
  ・BYTEデータを列記します
  ・何もデータがない場合はエラーとします
  ・式が文字列を返す場合は、先頭から シフトJIS で切り出します
    'ABC'     → DB  41H,42H,43H
    'あいう'  → DB  82H,A0H,82H,A2H,82H,A4H
  ・1PASS目に式(条件式を含む)が解決できなかった場合は「数値(1件のデータ)」
    として処理を進めます
    したがって、2PASS目で解決された結果が文字列だった場合はエラーになります
    これはバイナリサイズが変わってしまうのが理由です
   「undef?"ABC":"DEF"」の様に件数が自明のケースもありますが同様とします
  ・「$」はソース一行の処理が終わるまで変化しません


  □DEFW 式 [,式 [, ...]]
  □DW   式 [,式 [, ...]]
  □FDB  式 [,式 [, ...]]
  ~~~~~~~~~~~~~~~~~~~~
  ・WORDデータを列記します (SC/MP のみ Big Endian)
  ・何もデータがない場合はエラーとします
  ・式が文字列を返す場合は、先頭から シフトJIS で切り出します
    常に 2byte 出力し、バイトオーダー設定の影響を受けるので非推奨です
    'ABC'     → DB  41H,00H,42H,00H,43H,00H ; 8080,8085,Z80
    'あいう'  → DB  A0H,82H,A2H,82H,A4H,82H ; 8080,8085,Z80
    'ABC'     → DB  00H,41H,00H,42H,00H,43H ; SC/MP
    'あいう'  → DB  82H,A0H,82H,A2H,82H,A4H ; SC/MP
  ・1PASS目に式(条件式を含む)が解決できなかった場合は「数値(1件のデータ)」
    として処理を進めます
    したがって、2PASS目で解決された結果が文字列だった場合はエラーになります
    これはバイナリサイズが変わってしまうのが理由です
   「undef?"ABC":"DEF"」の様に件数が自明のケースもありますが同様とします
  ・「$」はソース一行の処理が終わるまで変化しません


  □その他の擬似命令
  ~~~~~~~~~~~~~~~~~~~~
  ・RELAXED   AS : 数値フォーマット拡張SW

  ・SKIP      Z80 EDAS : 改ページ指定
    文字列のコメントが付いた場合のみ改ページ指定とします
    コメントには長さ0の文字列, 文字型(数値を含む) も受け付けます
    この変更により「SKIP」は意図しない限りラベルと判定されるようになります
    SKIP  "--------"
    SKIP  ""
    SKIP  'X'
    SKIP  8001
    SKIP          ; この skip はラベルになります
    SKiP  XOR A   ; この SKIP はラベルになります


==============================================================================
■オペコード

------------------------------------------------------------------------------
  □オペコード [オペランド予約語|式 [,...]]
  ~~~~~~~~~~~~~~~~~~~~
  ・オペコード, オペランド予約語は大文字/小文字を区別しません
  ・オペランドに過不足がある場合はエラーとします
  ・オペランドはシンボルよりレジスタ名やコンディションコード等が優先されます
  ・表記毎の制限事項等は巻末の「特記事項」を参照してください


==============================================================================
■ラベル

------------------------------------------------------------------------------
  □ラベル(シンボル)
  ~~~~~~~~~~~~~~~~~~~~
  ・ラベルを定義します
    複数のラベルを同じ行で定義できません (logの見やすさ優先)
    ラベル定義に問題があった場合、その行すべての記述が無視されます
  ・擬似命令(シンボル定義含む),オペコード,マクロ定義以外はすべてラベルとします
  ・末尾の「:」はラベル名に含めません
  ・ラベル名は大文字/小文字を区別します
  ・ラベル名の制限
    ・「数値として評価対象となる文字列」は使用できません
    ・演算子として使用する文字を含む文字列は使用できません
    ・「"」,「'」を含む文字列は使用できません
  ・ラベルは再定義できません
    シンボルと同じ管理ですので重複できません
    マクロ名とは別管理ですので重複可能です
  ・ラベルにはオペレーションカウンタの値が設定されます
    ラベルの値は常に「アドレス型」となります
    「アドレス型」の値は相対アドレスの計算対象となる場合があります
  ・ラベルは「.」を使って「PREFIX.suffix」の構成とすることができます
    ・「.suffix」は無くてもかまいません
    ・PREFIX の「値(アドレス)」は PREFIX が単独で指定された場合のみ設定されます
    ・suffix はラベル名先頭の「.」から後ろの文字列になります
  ・「ローカル・ラベル」と「現在のPREFIX(名前空間)」について：
    ・"." で始まらないラベルを定義する際に「現在のPREFIX」が更新されます
     「現在のPREFIX」はラベル名先頭から最初の「.」までの文字列になります
     「MAIN」,「MAIN.」,「MAIN..」は「MAIN」が「現在のPREFIX」になります
      飛び地にデータを置きたい場合などにラベルの重複を回避して同じ名前空間を
      設定できます
    ・"." で始まるラベルを「ローカル・ラベル」と呼びます
      ・ローカル・ラベルは定義時に「現在のPREFIX」を補完します
        但し「現在のPREFIX」が未定義の場合は何もしません
      ・ローカル・ラベルは引用時に「現在のPREFIX」を補完します
        但し「現在のPREFIX」が未定義の場合は何もしません
        ※suffix のみで一意に決まる場合も PREFIX を補って検索します
          したがって、PREFIX が一致しない場所ではエラーになります

    ※上記仕様により、定義,引用の仕方で対象のラベルが異なります
      a)「PREFIX.suffix」
                         名前空間  ラベル
      a-1) MAIN.loop  ⇒ MAIN      MAIN.loop  (記述どおり)
      a-2) MAIN..loop ⇒ MAIN      MAIN..loop (記述どおり)

      b) ローカルラベル (ラベル-名前空間一致)
                         名前空間  ラベル
      b-1) MAIN:      ⇒ MAIN      MAIN
           .loop          └──→ MAIN.loop  (名前空間を補完する)
      b-2) MAIN:      ⇒ MAIN      MAIN
           ..loop         └──→ MAIN..loop (名前空間を補完する)

      c) ローカルラベル (ラベル-名前空間不一致)
                         名前空間  ラベル
      c-1) MAIN.:     ⇒ MAIN      MAIN.
           .loop          └──→ MAIN.loop  (名前空間を補完する)
      c-2) MAIN.:     ⇒ MAIN      MAIN.
           ..loop         └──→ MAIN..loop (名前空間を補完する)

  ・テンポラリ・ラベル：
    ・マクロ中では「テンポラリ・ラベル」が展開されます
    ・PREFIX を補完した後で、最初に見つけた「#」の直後に ローカルID を補完します
     「#」が PREFIX 側に置かれた場合も同様です
      ※マクロ外では補完しません
    ・ローカルIDは「#0000」から始まり「#FFFF」を上限とします
      ローカルIDはマクロの呼び出し(ループマクロでは各ループ)毎に +1 されます
    ・ユーザーが ローカルID を知る方法はありません
      ローカルID の桁数や決定ロジックは将来変更する可能性があります
    ・MC6800 の immediateモードを示す冒頭の「#」は ローカルID挿入位置としません
      MC6800 では「#」から始まるラベルが使えないことがあります

==============================================================================
■エラーメッセージ

------------------------------------------------------------------------------







==============================================================================
■特記事項

------------------------------------------------------------------------------
  □i8080 (Intel Mnemonic)                                          Asm2ObjI80
  ~~~~~~~~~~~~~~~~~~~~
  ・RST の第一オペランドは「オペコードの引数」です
    1PASS目に解決できなかった場合はエラーとなります

------------------------------------------------------------------------------
  □i8080 (Zilog Mnemonic)                                          Asz2ObjI80
  ~~~~~~~~~~~~~~~~~~~~
  ・RST の第一オペランドは「オペコードの引数」です
    1PASS目に解決できなかった場合はエラーとなります

------------------------------------------------------------------------------
  □i8085 (Intel Mnemonic)                                          Asm2ObjI85
  ~~~~~~~~~~~~~~~~~~~~
  ・RST の第一オペランドは「オペコードの引数」です
    1PASS目に解決できなかった場合はエラーとなります

  ・追加命令
    ・RIM       Read Interrupt Mask
    ・SIM       Set Interrupt Mask

  ・未定義命令
    ・DSUB      HL <- HL - BC
    ・ARHL      HL <- HL >> 1, H3 <- H3, CY <- L0   (算術右シフト)
    ・RDEL      DE <- DE << 1, E0 <- CY, CY <- D3   (左ローテート)
    ・LDHI n    DE <- HL + n
    ・LDSI n    DE <- SP + n
    ・SHLX     (DE)<- HL
    ・LHLX      HL <-(DE)
    ・JNX5 lm   if(!X5) PC <- lm
    ・JX5  lm   if( X5) PC <- lm
    ・RSTV      if( V ) push PC, PC <- 0040H

------------------------------------------------------------------------------
  □i8085 (Zilog Mnemonic)                                          Asz2ObjI85
  ~~~~~~~~~~~~~~~~~~~~
  ・RST の第一オペランドは「オペコードの引数」です
    1PASS目に解決できなかった場合はエラーとなります

  ・追加命令
    ・RIM       Read Interrupt Mask
    ・SIM       Set Interrupt Mask

  ・未定義命令 (ザイログ風の表記も用意しました)
    ・DSUB      HL <- HL - BC                           SUB BC
    ・ARHL      HL <- HL >> 1, H3 <- H3, CY <- L0       SRA HL
    ・RDEL      DE <- DE << 1, E0 <- CY, CY <- D3       RL  DE
    ・LDHI n    DE <- HL + n                            LD  DE,  HL+n
    ・LDSI n    DE <- SP + n                            LD  DE,  SP+n
    ・SHLX     (DE)<- HL                                LD (DE), HL
    ・LHLX      HL <-(DE)                               LD  HL, (DE)
    ・JNX5 lm   if(!X5) PC <- lm                        JP  NX,  lm
    ・JX5  lm   if( X5) PC <- lm                        JP  X,   lm
    ・RSTV      if( V ) push PC, PC <- 0040H            RST V

    DSUB
      SUB HL,BC とすべきだと思いましたが、自明なので 8bit系の表記に合わせました
      このためだけに 8bit系を SUB A,r に変更するのもアレなので

    LDHI
      n=0 の場合、+n を省略できます
      LD DE,ADD HL,n の様な表記も考えましたが、HL は更新されないので止めました

    LDSI
      n=0 の場合、+n を省略できます
      LD DE,ADD SP,n の様な表記も考えましたが、SP は更新されないので止めました

    JNX5, JX5
      コンディションコードは NX5, X5 も使用できます

    RSTV
      V はコンディションコード(Overflow) です

------------------------------------------------------------------------------
  □Z80                                                             Asz2ObjZ80
  ~~~~~~~~~~~~~~~~~~~~
  ・外括弧の付いたオペランドを「ポインタ型」として扱います
    式に不要な括弧を付けないでください
      LD A,($8000+OFFSET) → LD r,(lm) ... OK
      LD B,($80+INDEX)    → LD r,(lm) のパターンに合致するが Bレジ対象は NG

  ・「ポインタ型」を要求する場面では自明であっても括弧を省略できません
      例 : OUT n,A は受け付けない
    ※古いアセンブラではOKなものもあるかも / 仕様変更の可能性あり

  ・RST, BIT, RES, SET, IM の第一オペランドは「オペコードの引数」です
    1PASS目に解決できなかった場合はエラーとなります

  ・OUT (C),0 の第二オペランドが1PASS目に解決できなかった場合はエラーとなります

  ・インデックスレジスタの表記 (大文字/小文字の区別なし)
    ・IX           / IY
    ・IXh, IXU, Xh / IYh, IYU, Yh
    ・IXl,      Xl / IYl,      Yl
    ・(IX+0) / (IY+0) の「+0」は省略可能

  ・特殊な未定義命令の表記
    ・RLC (I?+d),r   | LD r,RLC (I?+d)   | LD r,RLC(I?+d)
    ・RRC (I?+d),r   | LD r,RRC (I?+d)   | LD r,RRC(I?+d)
    ・RL  (I?+d),r   | LD r,RL  (I?+d)   | LD r,RL(I?+d)
    ・RR  (I?+d),r   | LD r,RR  (I?+d)   | LD r,RR(I?+d)
    ・SLA (I?+d),r   | LD r,SLA (I?+d)   | LD r,SLA(I?+d)
    ・SRA (I?+d),r   | LD r,SRA (I?+d)   | LD r,SRA(I?+d)
    ・SLL (I?+d),r   | LD r,SLL (I?+d)   | LD r,SLL(I?+d)
    ・SRL (I?+d),r   | LD r,SRL (I?+d)   | LD r,SRL(I?+d)
    ・RES n,(I?+d),r | LD r,RES n,(I?+d)
    ・SET n,(I?+d),r | LD r,SET n,(I?+d)
    ・IN  (HL),(C)   | IN  F,(C)         | IN  (C)
    ・OUT (C),(HL)   | OUT (C),0         | OUT (C)
    ※Asm2Obj 1.4.0～ カンマ切り要素の省略("0"で補完)が可能になりましたが
        LD r,RES n,(I?+d)
        LD r,SET n,(I?+d)
      の n は省略できません

  ・未定義命令のオブジェクトを生成できない命令
    ・LD (lm),HL   [22 lm]
      [ED 63 lm] は生成できません

    ・LD HL,(lm)   [2A lm]
      [ED 6B lm] は生成できません

    ・NEG          [ED 44]
      [ED 4C | ED 54 | ED 5C | ED 64 |ED 6C | ED 74 | ED 7C] は生成できません

    ・RETN         [ED 45]
      [ED 55| ED 5D | ED 65 |ED 6D | ED 75 | ED 7D] は生成できません

    ・IM 0         [ED 46]
      [ED 4E | ED 66 | ED 6E] は生成できません

    ・IM 1         [ED 56]
      [ED 76] は生成できません

    ・IM 2         [ED 5E]
      [ED 7E] は生成できません

------------------------------------------------------------------------------
  □MC6800                                                          Asm2ObjM60
  ~~~~~~~~~~~~~~~~~~~~
  ・アドレッシングモード「DIRECT/EXTEND」の判定は 1PASS目に行います
    アドレスがゼロページを指している場合は、常に DIRECTモードとします
    あえて EXTENDモードのオブジェクトを生成させる手段は用意していません

  ・1PASS目に式が「未解決」だった場合のアドレッシングモードは EXTEND とします
    2PASS目に解決されたアドレスがゼロページを指していても DIRECT としません

  ・レジスタ名を含んだオペコードの分かち書きに対応しています
    例 : INCA       → INC A
         ADDA #$5F  → ADD A,#$5F   ; ※Aの後ろにカンマが必要
         SUBB $80,X → SUB B,$80,X  ; ※Bの後ろにカンマが必要

------------------------------------------------------------------------------
  □SC/MP                                                           Asm2ObjN80
  ~~~~~~~~~~~~~~~~~~~~

  ・XPAL
   「XPAL P0」,「XPAL PC」を受け付けるか検討中 (現在は「受け付けない」)

  ・XPAH
   「XPAH P0」,「XPAH PC」を受け付けるか検討中 (現在は「受け付けない」)

  ・XPPC
   「XPPC P0」,「XPPC PC」を受け付けるか検討中 (現在は「受け付けない」)

==============================================================================
