-
Z80 Assembler Reference Manual
HI-TECH Cコンパイラシステムに同梱のアセンブラは機能完全版の、ザイログニーモニックを解するリロケータブルマクロアセンブラです。このニーモニック及び、Z80アセンブラ言語はザイログ社発行の「Z80アセンブリ言語ハンドブック」で記述されており、このマニュアルにもリファレンスとして含まれています。 アセンブラはオペランドに特定のexpressionを許容し、またここで記述される疑似命令も同様です。 アセンブラはHitachi64180や Z180プロセッサ用に追加されたオプコードも許容します。
使用法
アセンブラはZASという名前で、次のように指定されます。
ZAS options files...
このファイルは一つ、もしくはそれ以上のアセンブル対象となるアセンブラソースファイルですが、注意すべきなのは、すべてのファイルが一つのファイルとしてアセンブルされることです。個別のファイルにはなりません。 個別のファイルにアセンブルするには、アセンブラがそれぞれのファイルに個別に指定されなければいけません。オプションは0個もしくはそれ以上んも次のオプションからなります。
- -N
- expressionの算術的なオーバーフローを無視します。-Nオプションは算術的オーバーフローを抑制します。アセンブラはオーバーフローの扱いにおいて「Z80アセンブリ言語ハンドブック」に従います。またある種のインスタンスにおいて、これはユーザーが意図していたものを実際に評価し、エラーとなります。このオプションはオーバーフローチェックのオプションを上書きするために使われます。
- -J
- 分岐ジャンプを最適化しようとします。-Jオプションはアセンブラに対してジャンプと条件ジャンプを、可能な部分であれば相対分岐としてアセンブルするようにリクエストします。分岐の等価物を持つこれらの条件ジャンプのみが最適化されます。ジャンプはターゲットが分岐の範囲内にある分岐のみが最適化されます。これはアセンブラに対して入力されたコードをパスに追加する必要があるため?このオプションの使用はアセンブルの速度を低下させます。
- -U
- 未定義のシンボルを外部関数として扱います。-Uオプションは未定義のシンボルに関するエラーメッセージを抑制します。このようなシンボルはどんな場合であっても、外部関数として扱われます。このオプションの使用は生成されたオブジェクトを変更しませんが、エラーメッセージの抑制をおこしません??
- -Ofile
- オブジェクトコードをファイル内に配置します。デフォルトオブジェクトファイル名は最初のソースファイル名から構築されます。ファイル名の中の拡張子やファイルの型(つまり、"."よりも右側)が切り取られ、拡張子.objが追加されます。そのため、以下のコマンド
ZAS file.as file2.z80
- はfile1.objというオブジェクトファイルを生成します。-Oオプションの使用はこのデフォルトの便利さを上書きし、オブジェクトファイルに任意の名前をつけることを許容します。たとえば
ZAS -ox.obj file1.obj
- x.objのオブジェクトコードの中にオブジェクトコードが配置されます。
- -Llist
- アセンブラのリスティングをlistファイルに置くか、listがnullの場合はリストファイルが-Lオプションで作成されます。
- もし、ファイル名がこのオプションに与えられると、その名前でリストファイルが作成され、それ以外の場合、リスティングは標準出力(つまりコンソールへ)書き出されます。
- CON:やLST:といったファイル名が使えます。
- -Wwidth
- このリスティングはプリンタを与えられたwidthの幅でフォーマットします。
- -Wオプションはリスティングがどれくらいの幅にするか、指定するオプションです。
ZAS -Llst: -W80 x.as
- これはlistデバイス80カラム用にリスティングを整形してアウトプットします。
- -C
- このオプションはZASに対し、クロスリファレンス情報を書くリクエストをします。
- このファイルはxxx.crfと呼ばれ、xxx は最初のソースファイル名の基本部分です。
- これはCREFユーティリティを走らせる時に必要で、この情報が整形されたリスティングに変わります。
エクスプレッション
エクスプレッションは「Z80アセンブリ言語ハンドブック」に記述されている内容で大部分が構成されます。
- | Subtraction減算 |
.and. | Bitwise ANDビット演算AND |
.eq. | Equality test同値か評価 |
.gt. | Signed greater than符号あり大なり |
.high. | Hi byte of operandオペランドの高位バイト |
.low. | Low byte of operandオペランドの低位バイト |
.lt. | Signed less than符号あり小なり |
.mod. | Modulusモジュール |
.not. | Bitwise complementビット演算 |
.or. | Bitwise orビット演算 |
.shl. | Shift left左シフト |
.shr. | Shift right右シフト |
.ult. | Unsigned less than符号なし小なり |
.ugt. | Unsigned greater than符号なし大なり |
.xor. | Exclusive orXOR |
/ | Divison除算 |
< | Signed less than符号あり小なり |
= | Equalityイコール |
> | Signed greater than符号あり大なり |
^ | Bitwise orビット演算 |
"."で始まるオペランドはスペースで区切る必要があります。label .and. 1 は有効ですがlabel.and.1は有効ではありません。
再配置性
zasは再配置可能なオブジェクトコードを生成します。つまりこれは、メモリのどこに配置すべきかをアセンブル時に指定しなくて良い、ということを意味します。
これはORG擬似命令を使うことで可能ですが、より好ましいアプローチはプログラムセクションあるいはpsectをつかうことです。
psectはプログラムのセクションに名前を付けたもので、この中のコードやデータさアセンブル時に定義されます。psectの全てのパーツは、別々のファイルで定義されていても、また同じファイル内で、別のpsectで分断されていたとしても、メモリに連続して読み込まれます。
例えば、次のコードはtextと名付けられたpsectに実行可能なインストラクションを。またdata psectにデータバイトを読み込みます。
psect text, global alabel: ld hl,astring call putit ld hl,anotherstring psect data, global astring: defm 'A string of chars' defb 0 anotherstring: defm 'Another string' defb 0 psect text putit: ld a,(hl) or a ret z call outchar inc hl jr putit
2つのブロックのtext psectが、data psectによって分断されていますが、2つのtext psectブロックはリンカに呼び出される時に連続します。
"ld hl,anotherstring"というインストラクションは実行時に"putit:"というラベルに落ちます??
2つのpsectの実際のメモリ位置はリンカによって決められます。psectアドレスがどのように決められるかについては、リンカのマニュアルを参照してください。
psect内で定義されるラベルにははリロケータブルになり、これはアセンブル時には実際のメモリアドレスが定義されないということです。
ラベルがデフォルトの(名前のない)psectの場合、もしくは絶対定義(PSECT擬似命令の記述参照)した場合には適用されません。
絶対psect内で定義されたラベルはアセンブラによってアドレスが決められ、絶対指定になります。
HI-TECH Cのバージョン7もしくはそれ以降のバージョンと一緒に提供されるZASは、リロケータブルエクスプレッションが、エクスプレッション内で自由に結合します。古いバージョンのZASは、リロケータブルエクスプレッションが算術的に限られます??
擬似命令
擬似命令は、"Z80アセンブリ言語ハンドブック"の記述に依拠し、いくつかの追加があります。
DEFB, DB
- この擬似命令はエクスプレッションのコンマ区切りリストの後に置かれます。
- 一続きのバイトロケーションにアセンブルされます。
- どのエクスプレッションも-128から255の値を内包する必要があります。
- DBはDBFBのシノニムとして使うことができます。
例:
DEFB 10, 20, 'a', 0FFH DB 'hello world',13,10,0
DEFF
- この擬似命令は浮動小数点数コンスタントを32bitのHI-TECH Cフォーマットの浮動小数点数コンスタントにアセンブルします。
例
pi: DEFF 3.14159
DEFW
- エクスプレッションを値に制限のないワードにアセンブルすること以外はDEFBと似ています。
例:
DEFW -1, 3664H, 'A', 3777Q
DEFS
- DEFSは初期化することなしにメモリロケーションをリザーブします。
- このオペランドは絶対的なエクスプレッションで、リザーブされるされるバイト数を表現します。
- このエクスプレッションは現在のロケーションカウンターに追加されます。
- しかしながら、DEFSによってリザーブされたロケーションがプログラムの中間の場合、リンカによってゼロに初期化される可能性があります。
例:
DEFS 20h ;メモリの32バイトをリザーブ
EQU
- EquはEQUの左に、シンボルの値を右にエクスプレッションを設定します。
- 既にていぎされているシンボルの値を設定するのは違反です。
- 例:
SIZE equ 46
DEFL
- 既に存在するシンボルを再定義できることを除いて、EQUと同じです。
例:
SIZE defl 48
DEFM
- DEFMはシングルクォートで囲まれた、文字列の後に続かなければいけません。
- これら文字のASCII コードは連続したメモリにアセンブルされます。
例:
DEFM 'A string of funny *@$ characters'
END
- ソースファイルの終わり、もしくは擬似命令ENDがアセンブルの終了を意味します。
- 擬似命令ENDはオプション的に、プログラムの開始アドレスを定義するエクスプレッションに続いて現れることがあります。
- これはCP/Mでは本当のところ、便利ではありません。ただ1つの開始アドレスだけがプログラムごとに定義されます。それ以上ある場合はリンカが文句をいいます。
例:
END somelabel
COND, IF, ELSE, ENDC
- 条件的アセンブルはCOND擬似命令によって、提供されます。
- CONDのオペランドは絶対的なエクスプレッションでなければいけません。
- もし、この値が偽(ゼロ)の場合、CONDから続き、対応するENDC擬似命令の部分まではアセンブルされません。
- COND/ENDCのペアはネストが可能です。
- IFがCONDのシノニムとして使用可能です。
- ELSE擬似命令をCOND/ENDCブロックの中に含むことができます。
例:
IF CPM call 5 ELSE call os_func ENDC
ELSE
- COND参照
ENDC
- COND参照
ENDM
- MACRO参照
PSECT
- この擬似命令は再配置可能なプログラムセクションの定義を許可します。
- この引数はオプション的にpsectフラッグの後に着く、psect nameです。
- psect名はラベルと同じルールに従って構築されるシンボルですが、psectは、衝突することなくラベルと同じ名前を持つことができます。
- psect名はPSECT擬似命令の後で、のみ認識されます。psectフラグは以下の通りです。
- ABS
- Psectは絶対値です。
- GLOBAL
- Psectはグローバルです。
- LOCAL
- Psectはグローバルではありません。
- OVRLD
- Psectはリンカによってオーバーラップ可能です
- PURE
- Psectはリードオンリーでなければいけません
- Psectがもしグローバルな場合、リンカはこれを、他モジュールで同名の他のグローバルpsectとマージします。
- ローカルのpsectは他のモジュールからの、他のpsectとは区別されます。Psectはデフォルトでグローバルです。
- デフォルトでリンカはいろいろなモジュールからのpsect内で、コードを連結します。
- psectがOVRLDとして指定されると、リンカがそれぞれのモジュールを、そのpsectにオーバーラップしていきます。
- 初期化する時や、ベクター割り込みする時など、モジュールをリンクをする特定の場合に便利です。
- PUREフラグは、psectが実行時にのみリードオンリーになり得るとリンカに伝えます。
- このフラグの有用性はリンカが要求を強制する能力に依存します。CP/Mは悲しいことに、ここに配慮されていません?
- ABSフラグはpsectを絶対化します。
- psectはゼロに読み込まれます。
- これは静的にベクター割り込みを初期化し、テーブルにジャンプする時に有用です。
例:
PSECT text, global, pure PSECT data, global PSECT vectors, ovrld
GLOBAL
- GLOBAL はもう1つのシンボルに続いて(カンマ区切りで)使われなければいけません。これはinternalでもexternalでも、現在のモジュールの内部で依存していてもいなくても、アセンブラにグローバルとして取り扱われます。
- 例:
GLOBAL label1, putchar, _printf
ORG
- 擬似命令ORGは現在のpsectをデフォルト(絶対)psectに設定し、絶対表現としなければならないロケーションカウンタをオペランドとします。
例:
ORG 100H
MACRO
- この擬似命令はマクロを定義します。マクロ名に前置する要素も後続する要素もあります。
- カンマ区切りのフォーマルパラメータがオプション的に後続します。
- MACRO擬似命令に後続し、次のENDMまでのコードの行がマクロ本体として格納されます。
- マクロ名は後続するアセンブラステートメントのオプコード部分でも使われ、実際のパラメータが後続します。
- マクロの本体は、その部分で、対応する実際のパラメータを持つフォーマルパラメータと置き換えられます??
- 例:
print MACRO string psect data 999: db string,'$' psect text ld de,999b ld c,9 call 5 ENDM
- 使用されると、このマクロはマクロの本体で、実際のパラメータの代用である関数と引数の3つのインストラクションに展開されます??
- 従って、print hello world' は次のように展開されます。
psect data 999: db 'hello world','$' psect text ld de,999b ld c,9 call 5
- マクロの引数はかぎ括弧('<' と '>')で閉じてコンマなどのデリミタキャラクタを含む任意のテキストを渡すために使うことが可能です。
- 例えば、キャリッジリターンとラインフィードを含む文字列を先ほど定義したprintマクロで使いたいとしましょう。
その場合のマクロを以下のように発動させたとします。
print 'hello world',13,10
- しかしこれは失敗します。なぜなら13と10が追加の引数として扱われて、無視されるからです。コンマを含む文字列を単体の引数として渡すためには、次のように書きます。
print <'hello world',13,10>
- これで 'hello world',13,10というテキストを単体の引数として渡すことができるでしょう。これは次のようなコードに展開されます。
psect data 999: db 'hello world',13,10,'$' psect text ld de,999b ld c,9 call 5
- ZASは古いバージョンのZASや他のZ80アセンブラとの互換性のため、2種類のマクロ定義をサポートしています。
マクロ名はMACRO擬似命令の前のラベルフィールドでも、MACRO擬似命令の後のオペランドフィールドでも定義できます。
- そのため、この2つのマクロ定義は等価です。
bdos MACRO func,arg ld de,arg ld c,func call 5 ENDM
MACRO bdos,func,arg ld de,arg ld c,func call 5 ENDM
LOCAL
- LOCAL擬似命令はマクロの拡張のため、ユニークなラベルを定義できます。
- LOCALディレクティブの後にシンボルがリスト化されている場合、マクロが展開される時に、これらは代わりの
- ユニークなアセンブラ生成シンボルとなります。
- 例
copy MACRO source,dest,count LOCAL nocopy push af push bc ld bc,source ld a,b or c jr z,nocopy push de push hl ld de,dest ld hl,source ldir pop hl pop de nocopy: pop bc pop af ENDM
- nocopyの位置に展開されたコードがユニークなアセンブラ生成ラベルを含む場合には、例えば、copy(recptr),buf,(recsize)は次のように展開されます。
push af push bc ld bc,(recsize) ld a,b or c jr z,??0001 push de push hl ld de,buf ld hl,(recptr) ldir pop hl pop de ??0001: pop bc pop af
- 2回目に発動する際には、nocopyラベルは??0002に展開されます。
REPT
REPT擬似命令は引数によって指定されただけ、複数回展開されるテンポラリマクロを定義します。
例:
REPT 3 ld (hl),0 inc hl ENDM
これは次のように展開されます。
ld (hl),0 inc hl ld (hl),0 inc hl ld (hl),0 inc hl
IRP と IRPC
IRPとIRPCディレクティブはREPTに似ていますが、ブロックを決まった回数繰り返すのではなく、引数リスト化にある回数それぞれを一回だけ実行します。
IRPの場合はリストはコンベンショナルマクロの引数リスト、IRPCの場合は文字列からの連続する文字です。
例:
IRP string,<'hello world',13,10>,'arg2' LOCAL str psect data str: db string,'$' psect text ld c,9 ld de,str call 5 ENDM
これは次のように展開されます。
psect data ??0001: db 'hello world',13,10,'$' psect text ld c,9 ld de,??0001 call 5 psect data ??0002: db 'arg2','$' psect text ld c,9 ld de,??0002 call 5
コンベンショナルマクロを使用する際と同様に、LOCALラベルとかぎ括弧の使用に注意してください。
IRPCを最もよく表す例は以下のものです。
IRPC char,ABC ld c,2 ld e,'char' call 5 ENDM
これは次のように展開されます。
ld c,2 ld e,'A' call 5 ld c,2 ld e,'B' call 5 ld c,2 ld e,'C' call 5
追加条件コード
このアセンブラはいくつかの追加条件コードを認識します。 これらは次の通りです。
Codeコード | Equivalent等価物 | Meaning意味 |
---|---|---|
alt | m | 数学的な"小なり"Arithmetic less than |
llt | c | 論理的な"小なり"Logical less than |
age | p | 数学的な"大なりイコール"Arithmetic greater or equal |
lge | nc | 論理的な"大なりイコール"Logical greater or equal |
di | ld a,iの後に使う | |
ei | 割り込み可能フラグの | |
評価です。それぞれ、 | ||
可能、不可能。 |
アセンブラディレクティブ
アセンブラディレクティブはソースファイルにおける行で、これはコードを生成せず、むしろアセンブラの振る舞いを変えます。
どのディレクティブも行の初めのカラムにアスタリスクがつくのでわかります。 これは単語のすぐあとにつき、最初の文字のみを見ます。
ディレクティブ自体を含む行はリスト化されません。ディレクティブは以下の通りです
- *Title
- このディレクティブ後続する行をリスティングのタイトルとして使います。
- *Heading
- このディレクティブに続く行をリスティングのサブタイトルとして使います。*Ejectにも影響します。
- *List
- ONやOFFを後に伴い、リストをそれぞれオンオフします。このディレクティブはマクロの内部や、そのマクロやインクルードファイルをコントロールするインクルードファイルでも使われる可能性があります。
- 以前のリスティング状態はマクロやインクルードファイルから戻った時に回復されます。
- *Include
- ディレクティブに後続するファイル名が、この時点でアセンブラにインクルードされます。
- *Eject
- 新しいページをこの時点で開始します。ソースのフォームフィールド文字も同じ効果を持ちます。
- これらのディレクティブのいくつかの例を挙げます。
*Title Widget Control Program
*Heading Initialization Phase
*Include widget.i
診断
アセンブル中に遭遇したそれぞれのエラーに対してエラーメッセージが標準エラーストリームに書き出されます。 このメッセージはファイル名と行番号を特定し、エラーを記述します。
エラーの起きた行のリスティングに加えて、エラーを示す1文字のフラグが立ちます。
文字と対応するメッセージは次の通りです。
- A
- Absolute expression required絶対表現が必要です。
- B
- Bad arg to *Lの引数が不正です
- Bad arg to IMの引数が不正です
- Bad bit numberビット番号が不正です
- Bad character constant文字定数が不正です
- Bad jump conditionジャンプ条件が不正です
- D
- Directive not recognized認識されないディレクティブです
- Digit out of range数字が範囲外です
- E
- EOF inside conditionalEOFが条件の中にあります
- Expression error
エクスプレッションエラーです
- G
- Garbage after operandsオペランドの後にガーベジがあります
- Garbage on end of line行末にガーベジがあります
- I
- Index offset too largeインデックオフセットが大きすぎます
- J
- Jump target out of rangeジャンプターゲットが範囲外です
- L
- Lexical errorレキシカルエラーです
- M
- Multiply defined symbolシンボルを複数回定義しました
- O
- Operand errorオペランドエラーです
- P
- Phase errorフェーズエラーです
- Psect may not be local and global
psectはローカルとグローバルにできません
- R
- Relocation errorリロケーションエラーです
- S
- Size errorサイズエラーです
- Syntax error構文エラーです
- U
- Undefined symbol未定義のシンボルです
- Undefined temporary label未定義のテンポラリラベルをです
- Unterminated string閉じていない文字列です
Z80/Z180/64180 インストラクションセット
この章の残りの部分はZ80、Z180、64180、NSC800の完全なインストラクションセットのために割かれています。Z180と64180 は全てのZ80の命令が実行できますが、タイミングが異なります。