Z80 Absolute Assembler 'Z80AS'

 Z80AS.EXE は Win32 コンソール上で動作する Z80用のクロスアセンブラです。


使い方

 Z80AS [<オプション>] <入力ファイル> [, <入力ファイル> ...]

 <入力ファイル> をアセンブルしてバイナリファイルを出力します。デフォルトではヘッダなどのついていない生のバイナリを出力するようになっています。出力形式はオプションで変更することができます。
 <入力ファイル> を複数指定することもできます。ただし、Cコンパイラなどと違いラベルの名前空間がファイルごとに分割されていないため、ラベルの命名には注意が必要です。

オプション

-o <出力ファイル>
出力するファイル名を指定します。このオプションを指定しない場合、デフォルトの出力ファイル名は入力ファイルの拡張子を ".BIN"(または指定した出力形式のデフォルトの拡張子) に変更したものになります。

-m <テープイメージ内のファイル名>
MZT形式のテープファイルイメージを出力します。出力するファイル名は、入力ファイルの拡張子を ".MZT" に変更したものになります。
ソースファイル内の ORG擬似命令で指定したアドレスがロードアドレスに、END擬似命令で指定したアドレス(なければロードアドレスと同じアドレス)が実行アドレスに設定されます。
<テープイメージ内のファイル名> に英小文字を使用すると、互換モニタ上では正しく表示されないようです。
<テープイメージ内のファイル名> に空白文字を含めたいときは、ダブルクォートで囲んでください。

-2 <IPL起動するプログラム名>
簡易的にMZ-2000用のD88ディスクイメージ形式(2D)のファイルを出力します。出力するファイル名は、入力ファイルの拡張子を ".d88" に変更したものになります。
MZ-2000用のIPL起動のプログラムは、メインメモリの0000hにロード・実行される形式で作成する必要があります。
バイナリ本体はセクタ番号30hから連続して格納されます。

-8
バイナリにIPLを付加し、簡易的にPC-8801用のD88ディスクイメージ形式(2D)のファイルを出力します。出力するファイル名は、入力ファイルの拡張子を ".d88" に変更したものになります。
0000h〜EFFFhの範囲のメインメモリにバイナリをロードして実行することを想定しています。実行開始時、0000h〜7FFFhはメインRAMになっています。
ソースファイル内の ORG擬似命令で指定したアドレスがロードアドレスに、END擬似命令で指定したアドレス(なければロードアドレスと同じアドレス)が実行アドレスに設定されます。
バイナリ本体はトラック1・セクタ1から連続して格納されます。

-i
Intel HEX形式のファイルを出力します。出力するファイル名は、入力ファイルの拡張子を ".HEX" に変更したものになります。

-l
-l:<フィルタ文字列>
ラベルとその値をリストファイルに出力します。出力するファイル名は、入力ファイルの拡張子を ".lst" に変更したものになります。
コロンの後に<フィルタ文字列>を指定すると、ラベル名の先頭が<フィルタ文字列>と一致するもののみ出力します。

-x
アセンブルリストを出力します。出力するファイル名は、入力ファイルの拡張子を ".als" に変更したものになります。

-D<ラベル名>=<値>
アセンブル開始前に、ラベルに値を定義します。

-T
MZTファイルの生成時に、配置されるアドレスがD000hを超えるようなバイナリが出来る場合、D000h以降を "D000.bin" というファイルに分割して出力します。"D000.bin" を2段ロードの1段目のプログラムに BINCLUDE するなどして利用できます。

-Y
CP/Mで標準的に使われている形式のシンボルテーブルリストを出力します。出力するファイル名は、入力ファイルの拡張子を ".sym" に変更したものになります。

ソースファイルの書式

ニーモニック

 ニーモニックの書式は、標準的なザイログ・ニーモニックのZ80アセンブラに従います。ニーモニックおよびレジスタ名は大文字小文字を区別しません。

未定義命令

コンディションコードの拡張書式

 JP, CALL, RET命令のコンディションコードにおいて、'NV', 'V' が使用できます。
 'NV' は 'PO' と同じ、'V' は 'PE' と同じと解釈されます。

ラベル

 ラベルに使用できる文字は、英数字・アンダーバー'_'・'#' および '?' です。ラベルは数字で始まってはなりません。ラベルは大文字小文字が区別されます。
 ラベルに定義できる値は 16ビット整数値(0000h〜0FFFFh)です。

 <ラベル名> の後にコロン':' を置くと、現在のロケーションカウンタを値として指定の名前のラベルを定義します。

 <ラベル名> の後にコロン2つ'::' を置くと、現在のロケーションカウンタを値として指定の名前のグローバルラベルを定義します。

即値

 10進数、16進数、2進数およびシングルクォート''' で囲まれた文字列が使用できます。
 16進数は数字[0-9]で開始し、'H'で終了します。
 16進数には'$'または"0x"で開始する形式も使用可能です。
 2進数は 'B'で終了します。
 数値中にはアンダーバー'_'を区切り記号として記述できます。アンダーバー'_'は単に無視されます。

例) LD      HL, 0D000H
    AND     0011_0101B

 シングルクォートで囲んだ文字列は、一番右の文字が最下位バイトとなります。
 32ビットまで有効です。

例) 'ABC' == 00414243H

 Z80AS では、即値やアドレスを指定する箇所に式を使用することができます。使用できる演算子と優先順位は、下の表のとおりです。

優先順位演算子備考
1()括弧内
2+ - ! ~正記号 負記号 論理NOT ビット反転
3* / %乗算 除算 剰余
4+ -加算 減算
5<< >>左シフト 右シフト
6< <= > >=算術比較
7== !=算術比較
8&ビットAND
9^ビットXOR
10|ビットOR
11&&論理AND
12||論理OR
13:8ビット整数値2つを16ビット整数値1つに合成

コロン演算子 ':'

 コロン演算子 ':' は、8ビット整数値2つを16ビット整数値1つに合成します。
 x:y は ((x << 8) | y) と同値です。

メモリアドレッシングモードに関する注意

 標準的なザイログ・ニーモニックでは括弧 '(' ')' を使ってメモリアドレッシングモードを指定します。Z80AS では式の優先順位を変えるためにも同じ括弧を使用しているため、表記が曖昧になる場合があります。オペランドの式全体が括弧でくくられている場合、メモリアドレッシングモードが指定されたものとみなします。メモリアドレッシングモードが指定できないオペランドでは、式全体が括弧でくくられていても即値とみなします。

ソースアセンブル結果
LD A,(1+2)*33E 09
LD A,((1+2)*3)3A 09 00
LD A,(1+2)*(3+4)3E 15
LD B,((1+2)*3)06 09

コメント

 ';' 以降の行末まではコメントとみなされ、無視されます。

ロケーションカウンタ

 '$' で現在のロケーションカウンタを参照することができます。オペランド中で参照した場合は、アセンブル中の命令の先頭アドレスを返します。

        ORG     0100H
        LD      HL, $      ; 21 00 01
        JR      $          ; 18 FE

ローカルラベル

 @@ および @0 〜 @9 の11個のローカルラベルを定義することができます。
 @b および @0b 〜 @9b で直前の @@ および @0 〜 @9 を参照します。
 @f および @0f 〜 @9f で直後の @@ および @0 〜 @9 を参照します。

ローカルラベルの使用例

@1:     LD      A, (HL)
        CP      'A'
        JR      C, @f
        CP      'F'+1
        JR      NC, @1f
@@:     INC     HL
        DJNZ    @1b
@1:

擬似命令

ORG <式>
ロケーションカウンタの値を<式>に変更します。<式>は評価時に決定されていなければなりません。
ソースファイル内で最初に記述されたORG擬似命令の <式> の値がロードアドレスとして使用されます(出力形式によってはロードアドレスの設定は無効です)。

END [<式>]
このソースファイルのアセンブルを終了します。<式>が指定された場合、<式>を実行開始アドレスとして設定します(出力形式によっては実行開始アドレスの設定は無効です)。

DB <式> [, <式> ...]
DB "<文字列>"
DB "<文字列>"+<即値>
<式>で指定されたバイト列を埋め込みます。<文字列>が指定された場合はアスキーコード列を埋め込みます。
<文字列>の後に +<即値> が指定された場合は、<文字列>の最後のバイトに指定した即値を加算します。

DW <式> [, <式> ...]
<式>で指定されたワード列を埋め込みます。

DS <式1> [, <式2>]
<式1>で指定されたバイト数の 0 を埋め込みます。<式2>が指定された場合はその値で埋めます。

ALIGN <式>
<式>で指定されたアラインメント境界までロケーションカウンタを進めます。空いた領域は 0 で埋められます。<式>の値は 2^n でなければなりません。

INCLUDE <ファイル名>
<ファイル名>で指定されたファイルを挿入します。

BINCLUDE <ファイル名>
<ファイル名>で指定されたバイナリファイルを読み込み、現在のロケーションに挿入します。

<ラベル名> EQU <式>
<式>の値を持つラベル <ラベル名> を定義します。

<ラベル名> = <式>
<式>の値を持つラベル <ラベル名> を定義します。このラベルは再度 '=' で定義しなおすことが可能です。
<式>は評価時に決定されていなければなりません。

<マクロ名> MACRO
ENDM
マクロ <マクロ名> の定義を開始します。次の行から ENDM の置かれた行までがマクロとして定義されます。
引数については何も指定する必要がありません。(展開時に引数の個数などを何もチェックしないため)

REPT <式>
ENDM
次の行から ENDM の置かれた行までを <式> で指定した回数分繰り返して展開します。
<式>は評価時に決定されていなければなりません。

IF <式>
ELSE
ENDIF
<式>の値が真(0以外)のとき、IF〜ELSE (ELSEがない場合は IF〜ENDIF) の間をアセンブルします。
<式>の値が偽(0)のときは、ELSE〜ENDIF の間をアセンブルします。
<式>は評価時に決定されていなければなりません。

OFFSET [<式>]
一時的にロケーションカウンタの値を<式>に変更し、END が出現するまでの間、バイナリを生成せずにロケーションカウンタだけを進めます。
構造体のメンバへのオフセット値をラベルに定義するために使用できます。
<式>が省略された場合は 0 を指定したものとみなします。<式>は評価時に決定されていなければなりません。

ERROR "<文字列>"
文字列をエラーとして出力し、アセンブルを終了します。

[<ラベル名>] PROC
ENDP
PROCENDPの範囲を独立した名前空間に分離します。
<ラベル名> が指定された場合は、新しい名前空間を作る前に、現在のロケーションカウンタを値としてラベルを定義します。
PROCENDP は省略形式の {} で記述することも可能です。

DISPC <式> [, <式> ...]
DISPC "<文字列>"
DB 擬似命令と同様ですが、こちらは <文字列> のASCII文字および半角カナ文字をMZ-700のディスプレイコードに変換したバイト列を埋め込みます。英小文字は英大文字に変換されます。MZ-700のディスプレイコードに存在しない文字は正しく変換されません。
半角カナ文字を使う場合、ソースコードをSJISで記述する必要があります。
<式> で指定した値については変換を行いません。

CHRMAP "<キャラクタマップ指定文字列>"
DB擬似命令に文字列を指定したときのコード変換方法を指定します。
指定文字列生成するバイト列
ASCIIアスキーコード(デフォルト、コード変換なし)
MZ-ASCII
MZ-ASCII-JP
MZアスキーコード(05hで大文字/小文字切り替え)
MZ-ASCII-EU海外版MZアスキーコード
DISPLAYCODEディスプレイコード
DISPLAYCODE-EU海外版MZディスプレイコード
USER-DEFINEDMAPCHR擬似命令で指定した文字コードマップ

MAPCHR <文字のASCIIコード>, <割り当てる値> [,<割り当てる値> ...]
DB擬似命令に文字列を指定したときのコード変換テーブルを作成します。作成したコード変換テーブルは、CHRMAP擬似命令で "USER-DEFINED" を指定した際に使用されます。
例) MAPCHR 'A', 01h, 02h, 03h  ; "ABC" を 01h,02h,03h に変換するテーブルを作る

ARRANGE <開始アドレス>, <配置バイト数>, <スキップバイト数> [, <配置バイト数>, <スキップバイト数> …]
DS擬似命令などで確保済みのバイナリ領域に、指定の方法でバイナリを配置(上書き)します。ARRANGE から END が出現するまでの間のバイナリに対し、指定のバイト数だけ配置し、その後指定のバイト数だけロケーションカウンタを進める、を繰り返します。

<ラベル名> PAGE_ALIGNED
PAGE_ALIGNEDの直後から行末まで、または直後にPROCENDPを記述した場合はその範囲を、256バイト境界(アドレスの下位バイトが00hになる位置)に自動配置します。範囲内のアセンブル結果は自動配置されるため、ソースコード上の記述順とバイナリ上の位置が一致しなくなりますので、ご注意ください。配置されるバイナリは256バイトを超えても問題ありませんが、256バイト以内に制限したい場合は IN_PAGE による指定を併用してください。

<ラベル名> IN_PAGE
IN_PAGEの直後から行末まで、または直後にPROCENDPを記述した場合はその範囲を、256バイト境界を跨がない(アドレスの上位バイトが変化しない)ような位置に自動配置します。範囲内のアセンブル結果は自動配置されるため、ソースコード上の記述順とバイナリ上の位置が一致しなくなりますので、ご注意ください。配置されるバイナリは256バイト以内である必要があります。

マクロ

 Z80AS のマクロは単純な文字列置換で実装されています。<マクロ名> をソース中に書くと、定義されたマクロの内容がそのまま展開されます。<マクロ名> の後には、マクロに渡す引数をカンマ ',' で区切って書くことができます。マクロ定義中の引数文字列 %1 〜 %9 は、<マクロ名> の後の引数に置換されます。
マクロ中で演算子'%'を使用する場合は、後ろにスペースを置き、引数と解釈されないようにしてください。
 マクロは1行中に1個しか記述できません。(マクロの後ろから行末までが引数と解釈されるため)

マクロ定義の例1
 PUSHM   MACRO
         IF '%1' PUSH %1 ENDIF
         IF '%2' PUSH %2 ENDIF
         IF '%3' PUSH %3 ENDIF
         IF '%4' PUSH %4 ENDIF
         IF '%5' PUSH %5 ENDIF
         IF '%6' PUSH %6 ENDIF
         IF '%7' PUSH %7 ENDIF
         IF '%8' PUSH %8 ENDIF
         IF '%9' PUSH %9 ENDIF
         ENDM

         PUSHM   AF, BC, DE, HL 
出力結果
         PUSH AF
         PUSH BC
         PUSH DE
         PUSH HL
マクロ定義の例2
 MLT     MACRO
         IF '%1' == 'BC' DB 0EDh,4Ch ENDIF 
         IF '%1' == 'DE' DB 0EDh,5Ch ENDIF
         IF '%1' == 'HL' DB 0EDh,6Ch ENDIF
         IF '%1' == 'SP' DB 0EDh,7Ch ENDIF
         ENDM

         MLT     HL
出力結果
         DB 0EDh,6Ch

IN_PAGE, PAGE_ALIGNED擬似命令の使用例

IN_PAGE, PAGE_ALIGNED擬似命令の使用例
 0000                    	ORG	1280h
 1280
 1280    3E 02           	LD	A, 2
 1282    CD 03 13        	CALL	table_jump
 1285    C9              	RET
 1286
 1300                    jump_table PAGE_ALIGNED IN_PAGE {   ; ←指定範囲を256バイト境界から配置し、
 1300    08              	DB	routine_a            ;   かつ256バイト以内に納めるため、
 1301    0B              	DB	routine_b            ;   PAGE_ALIGNEDIN_PAGE を指定
 1302    0E              	DB	routine_c
 1303
 1303                    table_jump::                        ; ←{ } で囲んだ範囲は名前空間が分離されるため、
 1303    26 13           	LD	H, jump_table >> 8   ;   ::を使ってグローバルラベルを定義
 1305    6F              	LD	L, A
 1306    6E              	LD	L, (HL)
 1307    E9              	JP	(HL)
 1308
 1308                    routine_a:
 1308    14              	INC	D
 1309    1C              	INC	E
 130A    C9              	RET
 130B
 130B                    routine_b:
 130B    15              	DEC	D
 130C    1D              	DEC	E
 130D    C9              	RET
 130E
 130E                    routine_c:
 130E    15              	DEC	D
 130F    1C              	INC	E
 1310    C9              	RET
 1311                    }
 1286
 1286    48 65 6C 6C     mes1	IN_PAGE	DB "Hello World!",0  ; ←{ } で囲まない場合、行末までが範囲となる
 128A    6F 20 57 6F                                         ;   jump_table を配置するために空けた1286h〜12FFhに 
 128E    72 6C 64 21                                         ;   配置されている
 1292    00
 1286