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

    8080,8085,Z80 のクロス開発を想定したアセンブラです
    インテル, ザイログの両ニモニックに対応しています
    オブジェクトはインテルHEX形式で出力ことができます
    エミュレータ(j80, u80)に組み込むためのモードを備えています
    ZASM(v1.64) に似たログを出力します

    具体的な使い方は、j80, u80, tools80 のドキュメントを参照してください

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

    ※暫定版です
      ・BIN, BAS形式(DISK BASIC のベタファイル) の出力に対応する予定です
      ・使用してはいけないアドレス範囲を定義できるようにする？
      ・展開したマクロのエラーログを何とかしたい
      ・エラーメッセージを丁寧にしたい
      ・式の分かち書き対策を検討中 → しばらく放置する予定
      ・引用ソースから *戻ってきた後で* END を取り消す擬似命令 (欲しい？)
      ・WINCLUDE (欲しい？)

==============================================================================
■ソース・ファイル
  ・文字コードは「Windows-31J」として解釈します
  ・ラベル以外は同一行に重複して記述できません
    主にログファイルの制限によるものです
    同じ理由で「ラベル[,ラベル]」や「ラベル,シンボル定義」も禁止しています
  ・カラムの区切り文字は 空白, カンマ, タブ です
    但し、下記優先順位で例外処理をしています
      1. 引用符の中の区切り文字は、区切り文字としません
      2. 括弧の中の空白は、区切り文字としません
    また「AF'」のアポストロフィについても特殊な処理をしています
  ・セミコロン(;) 以降はコメントとして扱います


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


==============================================================================
■式
  ・評価中は 符号付き32bit で処理します
  ・特記なき場合、0xFFFF でマスクされた値が返ります


------------------------------------------------------------------------------
  □演算子
  ~~~~~~~~~~~~~~~~~~~~
    (  )        : 右    
    ~  !        : 右   「!」: FALSE(0) ⇔ TRUE(0以外)
    *  /  %     : 左    
    +  -        : 左   「+」: 文字列の場合「連結」      <文字列対応>
    << >>       : 左    算術シフト
    <  <= >  >= : 左    非結合ではありません
    == !=       : 左    非結合ではありません            <文字列対応>
    &           : 左   「&」: 文字列の場合「連結」      <文字列対応>
    ^           : 左    
    |           : 左    
    &&          : 左    短絡評価はしません
    ||          : 左    短絡評価はしません
    ?  :        : 右    


  □定数
  ~~~~~~~~~~~~~~~~~~~~
    ・下記条件に当てはまるものを数値として評価します
      ・先頭が数字で始まる														...先頭が数字または「_」で始まる	とするか？
        ・「2001B」は数字として評価しますがエラーとなります
      ・先頭が「$」で、先頭の桁が「数字」または「A」-「F」
        ・「$_123」は数字として評価しません										...検討中「$_」を 00H として良いか？？？
      ・先頭が「@」で、先頭の桁が「0」-「7」
        ・「@_123」は数字として評価しません										...検討中「@_」を 00Q として良いか？？？
      ・「%」が式の冒頭にあるか「)」以外の演算子に続き、先頭の桁が「0」または「1」
        ・「%2001」は数字として評価しません
        ・「%1002」は数字として評価しますがエラーとなります
    ・フォーマット
      ・ 2進数：末尾に「B」または 先頭に「%」
      ・ 8進数：末尾に「O」または 「Q」または 先頭に「@」
      ・10進数：末尾に「D」または 数字(識別子なし)
      ・16進数：末尾に「H」または 先頭に「$」
    ・0xFFFF でマスクした値が返ります
    ・先頭となる桁以外の任意の桁に「_」を挿入できます


  □文字定数
  □文字列
  ~~~~~~~~~~~~~~~~~~~~
    ・「'」「"」または、一番外側の「{」から「}」で囲まれたもののうち
      一文字のものを文字定数、それ以外を文字列とします
      一番外側の「{」-「}」は、マクロを展開する際に区切り文字として扱われます
      test macro arg
           if "arg"=="A" ; arg は実引数に置換されません (文字列「arg」のまま)
           ...
           if arg=="A"   ; arg は実引数に置換され、シンボルとして評価されます
           ...
           if {arg}=="A" ; arg は実引数に置換され、文字列として評価されます
           ...
           endm

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

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

      LD macro reg1, reg2
        ;;; if reg1!="(HL)"     ; 置換された A や (HL) が評価されてしまう
        ;;; if "reg1"!="(HL)"   ; 実引数に置換されないのでダメ
            if {reg1}!="(HL)"   ; OK
            ld reg1, reg2
            endif
            endm

    ・エスケープ処理には対応していません
    ・文字定数は、数値(ASCIIコード/暫定)として評価しています
    ・文字列は連結(「+」,「&」) 比較(「==」,「!=」) が可能です
      演算子の少なくとも片方が文字列の場合、文字列の演算となります
     「長さ0の文字列」と連結した数値(文字定数を含む)は「文字列」になります
      比較演算の結果は数値となります
    ・三項演算中に文字列が含まれる場合
      ・条件式の評価結果が文字列になった場合はエラーとします
      ・真式,偽式のどちらかが文字列を返す可能性がある場合は、
        値を返した場合も文字(列)とします

        cond?"ABC":0
          → "ABC" か chr$(0) を返す

        cond1?(cond2?"ABC":1+1):0
          → "ABC" か chr$(1+1) か chr$(0) を返す
             ※chr$(1+1) は chr$(1)+chr$(1) とならないので注意

        cond1?(cond2?"ABC":""+1+1):0
          → "ABC" か chr$(1)+chr$(1) か chr$(0) を返す

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


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


==============================================================================
■擬似命令
  ・擬似命令では、余分なパラメータがあってもエラーとしません

------------------------------------------------------------------------------
  □IF 式
  □ELSEIF 式
  □ELSE
  □ENDIF
  ~~~~~~~~~~~~~~~~~~~~
    ・0:FALSE / 0以外:TRUE
    ・式が FALSE の場合、その節をスキップします
    ・式!FALSE の場合、次の節まで処理を進めます
      次の節が ELSEIF だった場合、ENDIF までスキップします
    ・スキップした行は、ログの先頭に ";;" と "-" を付けて出力します
    ・式が 1PASS目に解決できない場合はエラーとします
    ・ネスト可能です


  □REPT 式
  □ENDM
  ~~~~~~~~~~~~~~~~~~~~
    ・対応する ENDM までを 式の回数繰り返します (ループマクロ)
    ・式が 1PASS目に解決できない場合はエラーとします
      解決後の値(繰り返し回数/符号付32bit)が渡されます
    ・ループ回数が負の値だった場合はエラーとします
      ループ回数が 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
  ~~~~~~~~~~~~~~~~~~~~
    ・マクロを定義します
    ・「.」で始まる名前は使えません
    ・マクロ名末尾の「:」は無視します (1件のみ)
    ・マクロ名は再定義できません
      通常のシンボル(ラベル)と重複する名前も使用できますが、動作は保証しません
    ・マクロ名にニモニックや一部の擬似命令と同じ名前を使用して上書きできます
      但し、マクロ名は大文字小文字を区別しますので注意してください
      ・マクロ名に優先される擬似命令：IF, ELSE, ENDIF, REPT, IRP, IRPC, ENDM
        これらの名前は擬似命令が優先されます
        マクロを定義できますが使用できません
      ・マクロ名としても使用可能な擬似命令：MACRO
       「MACRO」という名前も使用可能で、マクロ定義に支障しません
        但し、呼び出し時に行頭にラベルを書くことができませんのでご注意ください
        (現状ではコロンを重視していない為、識別不能)
      ・上記以外：
        マクロ名が優先されるため、同名で引数の数が一致するものは使えなくなります
    ・仮引数は最大 16件 で、重複してはいけません
    ・仮引数の場所は、次のロジックで特定します
        1. 行を、区切り文字, 演算子に含まれる文字, 一番外側の"{"->"}" で分割する
           分割に用いる文字は検索対象に含まない
        2. 仮引数と同じ文字列を探す
      したがって、仮引数に演算子が含まれた場合、実引数は渡されません

    ・仮引数に演算子は使えません
    ・仮引数に未使用のものがあってもエラー, 警告を出しません
    ・マクロ定義はネストできません
    ・定義中にマクロの呼び出しやループマクロの定義を含めることができますが、
      循環チェックしていませんのでご注意ください


  □マクロ名 [[実引数],...]
  ~~~~~~~~~~~~~~~~~~~~
    ・名前と引数の数が一致したマクロを展開します
      一致するものがない場合、ここではエラーとしません
        sub macro regA,src
            sub src
            endm
     「sub (hl)」はそのままアセンブラに渡される  ←────────┐
     「sub a,(hl)」はマクロが「sub (hl)」に置換してから再評価される┘

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

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

        sample1 MACRO param
          LD A, param*10
        ENDM

        sample2 MACRO param
          LD A, (param)*10
        ENDM

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


  □END
  ~~~~~~~~~~~~~~~~~~~~
    ・それ以降のソースを無視します
      ネストしたマクロ中であっても展開を中止し、終了します
    ・無視した行はログに出力しません
    ・END の宣言がなくても、エラー,警告は出しません


  □BINCLUDE 式(ファイル名)[, 式(offset)[, 式(サイズ)]]
  ~~~~~~~~~~~~~~~~~~~~
    ・オペレーションカウンタからバイナリファイルを読み込みます
    ・式(ファイル名)
      1PASS目に解決できない場合, 文字列を返さない場合はエラーとします
    ・式(offset)
      省略した場合は 0 となります
      1PASS目に解決できない場合, 負の値だった場合はエラーとします
      ファイルサイズより大きな値でもエラーとしません
    ・式(サイズ)
      省略した場合はファイルサイズとなります
      1PASS目に解決できない場合, 負の値だった場合はエラーとします
      ファイルサイズを超える値でもエラーとしません
    ・読み込み中に EOF を超えた場合、指定サイズまで 0xFF で埋めます
    ・ログには読み込んだファイルの内容を記録しません (暫定仕様)
    ・BINCLUDE のみ、DS,DW で予約した領域を上書きできます (警告なし)
      逆に BINCLUDE で読み込んだ領域は DS,DW で再割り当てできません

  □INCLUDE 式(ファイル名)
  ~~~~~~~~~~~~~~~~~~~~
    ・INCLUDE先から戻った後、(ENDに達していなかったら)処理を続けます
    ・式が1PASS目に解決できない場合, 文字列を返さない場合はエラーとします
    ・ネスト可能ですが、循環チェックをしていませんのでご注意ください


  □CHAIN 式(ファイル名)
  ~~~~~~~~~~~~~~~~~~~~
    ・CHAIN先から戻った後、[EOF]までスキップします
    ・式が1PASS目に解決できない場合, 文字列を返さない場合はエラーとします
    ・スキップした行は、ログの先頭に ";;" を付けて出力します
    ・ネスト可能ですが、循環チェックをしていませんのでご注意ください
    ・マクロ中での動作は保障しません
      ※「CHAIN先から戻らない」のではないので注意
        INCLUDEファイルからCHAINした場合：
        ・INCLUDEファイルは CHAIN復帰後、[EOF]までスキップします
        ・INCLUDEファイルの親は INCLUDE復帰後、続きを処理します


  □ORG 式
  ~~~~~~~~~~~~~~~~~~~~
    ・オペレーションカウンタに値(アドレス)を設定します
    ・式(符号付32bit)が 1PASS目に解決できない場合はエラーとします
    ・式の値が負だった場合はエラーとします
      アドレスが 0xFFFFを超える場合は 16bitにマスクします
    ・何度でも設定可能ですが、オブジェクトを生成済みのアドレスは指定できません
    ※「label: ORG 式」と記述した場合 label は ORG 設定前のアドレスになります
      ログの該当行にはラベルではなく ORG で設定されたアドレスが記録されます
      ラベルとシンボル/ラベルの同一行定義と同じように禁止するかもしれません


  □DEFS 式[,式]
  □DS   式[,式]
  ~~~~~~~~~~~~~~~~~~~~
    ・オペレーションカウンタを進めます
    ・第一パラメータ
      ・スキップするバイト数
      ・式(符号付32bit)が 1PASS目に解決できない場合はエラーとします
      ・式の値が負だった場合はエラーとします
        スキップ中にアドレスが 0xFFFFを超えた場合は 16bitにマスクして続行します
    ・第二パラメータ
-     ・スキップした範囲は 00H で埋めます
-     ・第二パラメータがあった場合は、その値で埋めます
+     ※Ver. 0.6.7 から仕様を変更しました
+     ・第二パラメータが指定されていない場合はバイナリを生成しません
+       ただし、そのアドレスは「予約済み」として使用できなくなります
+       従来の動作に統一したい場合は、マクロで DS をオーバーライドしてください
+       例：
+         DS MACRO off
+            ds off,0   ; ※小文字 ds はオーバーライド対象にならない
+         ;  DEFS off,0 ; ※普段 DEFS を使わない方向け
+            ENDM
+     ・第二パラメータがあった場合はその値で埋めます
+       この場合はバイナリを生成します
++    ※Ver. 0.6.8 から仕様を調整しました
++    ・BINCLUDE のみ、DS,DW で予約した領域を上書き可能としました (警告なし)
++    ・逆に BINCLUDE で読み込んだ領域は DS,DW で再割り当てできません


  □DEFB 式[,式]...
  □DB   式[,式]...
  ~~~~~~~~~~~~~~~~~~~~
    ・BYTEデータを列記します
    ・何もデータがない場合はエラーとします
    ・式が文字列を返す場合は、先頭から ASCIIコード(暫定) で切り出します
      'ABC' → DB  41H,42H,43H
    ・式が文字列を含む場合、1PASS目に解決できない場合はエラーとします
      ※現状では、データ数が変わらない式の場合もエラーとなります
        UNDEF?"ABC":"DEF" (必ず3文字)
        "ABC"+UNDEF       (必ず4文字)
        →「"ABC",UNDEF」とすれば通る (1PASS目：41H,42H,43H, n)
      文字列を含まない式は 2PASS目に解決できない場合のみエラーとします
    ・「$」はソース一行の処理が終わるまで変化しません


  □DEFW 式[,式]...
  □DW   式[,式]...
  ~~~~~~~~~~~~~~~~~~~~
    ・WORDデータを列記します
    ・何もデータがない場合はエラーとします
    ・式が文字列を返す場合は、先頭から ASCIIコード(暫定) で切り出します
      'ABC' → DB  41H,00H,42H,00H,43H,00H
    ・式が文字列を含む場合、1PASS目に解決できない場合はエラーとします
      ※現状では、データ数が変わらない式の場合もエラーとなります
      文字列を含まない式は 2PASS目に解決できない場合のみエラーとします
    ・「$」はソース一行の処理が終わるまで変化しません


  □オペコード [[オペランド|式],...]
  ~~~~~~~~~~~~~~~~~~~~
    ・オペランドに過不足がある場合はエラーとします
    ・下記命令では式が 1PASS目に解決できない場合はエラーとします
      それ以外は、式が 2PASS目に解決できない場合はエラーとします
      ※8080/8085 : RST系
        Z80       : RST系, BIT操作系,「IM n」,「OUT (C),0」


  □シンボル EQU 式
  ~~~~~~~~~~~~~~~~~~~~
    ・シンボルを定義します
      ラベルと同じ行では定義できません (logの見やすさ優先)
    ・式として評価が可能な文字列はシンボルに使えません
      ※現在、定義時にはエラーとしていません
    ・「.」で始まる名前は使えません
    ・シンボル末尾の「:」は無視します (1件のみ)
    ・シンボルは再定義できません (ラベルと同じ管理です)
      但し、同じ値で上書きした場合はエラーとしません
      マクロ名とは別管理ですが、競合した場合の動作は保証しません
    ・シンボルの値に文字列は定義できません
    ・オペコードはシンボルとして使えません
    ・「$」はオペレーションカウンタをあらわす特別なシンボルとして定義済みです
    ・「$」は式の中で相対アドレスの計算対象となる場合があります
    ・ローカル および テンポラリ・シンボルが使用できます
      詳細は「ラベル」の項を参照してください
      定義時に PREFIX を更新しない点を除いてラベルと同じです
    ・式が 1PASS目に解決できない場合はエラーとします


  □シンボル(ラベル)
  ~~~~~~~~~~~~~~~~~~~~
    ・ラベルを定義します
      複数のラベルを同じ行で定義できません (logの見やすさ優先)
    ・数値(定数)として評価の対象となる文字列は使えません
      ※現在はチェックしていませんが、評価時にエラーになると思います
        内部処理で数字のラベルを使う予定があります
        そのときにチェックを追加します
    ・擬似命令, オペコード, シンボル定義でなかったものはすべてラベルとします
    ・ラベル末尾の「:」は無視します (1件のみ)
    ・ラベルは再定義できません (シンボル定義と同じ管理です)
      マクロ名とは別管理ですが、競合した場合の動作は保証しません
    ・ラベルにはオペレーションカウンタの値が設定されます
    ・ラベルは式の中で相対アドレスの計算対象となる場合があります
    ・ラベルは「.」を使って「PREFIX.suffix」の構成とすることができます
      ・"." で始まるラベルを「ローカル・ラベル」と呼びます
      ・ラベル定義時に「.」で始まっていなかった場合は PREFIX が更新されます
        PREFIX はラベル名先頭から最初の「.」までの文字列になります
      ・「.suffix」は無くてもかまいません
      ・定義時に PREFIX を省略した場合、現在の PREFIX を補完します
        但し、PREFIX が未定義の場合は何もしません
      ・引用時に PREFIX を省略した場合、現在の PREFIX を補完します
        但し、PREFIX が未定義の場合は何もしません
      ※引用時「.suffix」のみで一意に決定可能な場合も PREFIX を補って検索します
        したがって、PREFIX が一致しない場所ではエラーになります
    ・テンポラリ・ラベル：
      ・ループマクロ中では「テンポラリ・ラベル」が展開されます
      ・PREFIX を補完した後で、最初に見つけた「#」の直後に ループID を補完します
      ・補完された ループID は、ループを抜けると見えなくなります
       「#」が PREFIX 側に置かれた場合も同様です


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




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





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