HELP Contents

1 PMLエミュレータ使用ガイド

2 エミュレータの機能

3 PML言語リファレンス

3.1 ニーモニックの記述

3.1.1 基本構文

3.1.2 パラメータの書き方

3.1.3 数値表現

3.1.4 ラベルの書き方

3.2 PML命令

3.3 PML疑似命令

3.3.1 EQU:ラベル定義

3.3.2 DW:データセット

3.3.3 INCLUDE:ファイル挿入

3.3.4 MACRO:マクロ定義

3.3.5 PROC:ブロック化

3.3.6 UNIT:疑似モジュール化

3.3.7 USES:アクセス指定

3.4 アセンブルエラー

3.4.1 アセンブルエラーの表示と修正

3.4.2 エラーメッセージ

4 外部入出力機器リファレンス

5 高度な機能

6 汎用ルーチンリファレンス

Top Menu

3 PML言語リファレンス

このPMLアセンブラでアセンブルできるアセンブリ言語は次のような仕様になっています。

3.1 ニーモニックの記述

Page Top

3.1.1 基本構文

Page Top

PML用アセンブリ言語の基本構文は次のようになっています。

行ラベル: 	命令	 パラメータ1	 パラメータ2	 ;コメント

別にそれで区切りになるように作ることもできたんですが―――こういう物を扱う場合、世の中は基本的に全角文字ではアウトなので、あえて全角スペースとかがあっても区切りにならずエラーになるようにしています。

例えば以下のように書いてください。

>loop:	LD	X	#200h	;X番地に200hを代入する
	LD	Y	#300h	;Y番地に300hを代入する
	ADD	X	Y	;X番地の値とY番地の値を加算する
	SUB,	X,	#150h	;このようにカンマで区切ってもよい
	JP	>loop		;loopにジャンプする
	JP	>loop:		;loopにジャンプする
>loop:,	LD,	X,	#200h	;行ラベルのコロンの後にカンマは書けません。

3.1.2 パラメータの書き方

Page Top

ニーモニックのパラメータは本文にもあるように、以下の書き方が可能です。

書き方意味
#nnn#で始まるパラメータは即値すなわち、その値そのものとして扱われます。
@nnn@で始まるパラメータも即値すなわち、その値そのものとして扱われます。
nnn数値をただ書いた場合は参照値、すなわちその数値の示すアドレスに書かれている値として扱われます。
[ nnn ]このように角カッコで囲まれている場合は間接参照すなわち、そのアドレスに書かれた値のアドレスに書かれている値として扱われます。

3.1.3 数値表現

Page Top

アセンブラがパラメータを解釈する際に、その文字列がラベルとして定義されていればその値、定義されたラベルの中になければそれは数値表現であると見なして値を設定します。

数値表現の場合、まず末尾の文字を見てそれがどういう数値かを判断しています。

表記意味
nnnnが 0-9 の数字で末尾に特に何も付けなれば10進数として解釈される。
nnndnが 0-9 の数字で10進数であることを強調したければ最後にdをつける。
nnnhnが 0-9 および文字 A-F で、最後がhで終わればそれは16進数と解釈される。
nnnbnが数字の0または1で、末尾がbで終われば2進数と解釈される。
n$nが任意の1文字で$で終わる場合はその文字のシフトJISの文字コードになる。

以下は実際の表現例です。

表記実際の(10進数での)値
10010進数表現100
100d10進数表現100
100h16進数表現256
100b2進数表現8
aabbh16進数表現43,707
あ$文字コード表現33,440(82A0h)
a$文字コード表現97(61h)
ab$文字コード表現24,930(6162h) ←半角文字二つというのも実は○
§文字コード表現のエスケープ表記

文字列などを扱いたい場合はn$形式が便利ですが、以下の種類の文字はそのままでは表現できません。そのような文字を扱いたい場合は以下のようなエスケープ表記をするか、文字コードを直接値として使います。

エスケープ表記文字コード意味
\t09hタブ
\r0Dh復帰コード
\n0Ah改行コード
\s20hスペース
\c2Ch半角カンマ
\q27h半角シングルクォーテーション

3.1.4 ラベルの書き方

Page Top

ラベルとは本書内でも説明したとおりある数値と対応する文字列のことです。

ラベルの定義方法には下記の2種類があります。

  1. EQU疑似命令を使う。
  2. 行ラベルとして定義する。

EQU疑似命令とは例えば以下のような物で

	EAST	EQU	90

これは"EAST"という文字列に"90"という値を割り当てます。

またこのEASTという文字列は即値であるという気持ちをこめて

	#EAST	EQU	90

と定義してもOKです。

このあたりの事情については5.4ラベルが多すぎる!を参照して下さい。

行ラベルは

>loop:	LD	X	#200h	;X番地に200hを代入する

とプログラム行頭に書かれたラベルで、その値はその行の命令が入っているメモリアドレスをアセンブラが自動計算してセットします。上記の例ではLDという命令の入っているメモリアドレスが>loopの値になります。

使える文字の変な制限や行ラベルを>loopなどとしているのには結構深い理由があって、これらについても詳しくは5.4ラベルが多すぎる!を見て下さい。

	LD	X	#100h	;X番地に100hを代入する
>loop:
	LD	X	#200h	;X番地に200hを代入する
§ラベルの増分パラメータ

ラベルを記述する際に以下のように増分パラメータを付加することができます。

	#Y	EQU	100
	LD	X	#Y	;Xに値100をセット
	LD	X	#Y+1	;Xに値101をセット
	LD	X	#Y-1	;Xに値99をセット

すなわち"ラベル文字列+n"、"ラベル文字列-n"と記述することでそのラベルの値にnだけ加算、または減算された値を参照できます。

nは10進数で、0〜65535の範囲の数字でなければなりません。例えば下記のように書いたらエラーになります。

	LD	X	#Y+10h		←エラー

これを使えば例えば以下のようなラベルを作りたいような場合

X0:	DW	0
X1:	DW	0
X2:	DW	0
	LD	X0	#10
	LD	X1	#20
	LD	X2	#30

このような記述が可能になります。

X:	DW	0, 0, 0
	LD	X+0	#10
	LD	X+1	#20
	LD	X+2	#30
§絶対アドレス指定

行ラベルの形式で数値(正確には0〜9の数値で始まる文字列)を書くと、それはその行の絶対アドレス指定と解釈されます。

すなわち以下のように書けば、この命令は強制的に100番地に書き込まれ、以下の例ならばADD, X, YのADDは100番地になり、次の行のSUBが103番地になります。

100:	ADD	X	Y
	SUB	X	Z

ですが、これは本文で行番号付きで説明しているソースを動かすために導入したもなので、自分でプログラムするときはあまり意味がないというより、使わない方が無難です。何かに強制されて、命令やデータをとにかくメモリの指定されたアドレスに置かなければならない場合にのみ使用して下さい。

3.2 PML命令

Page Top

PML命令は以下の種類が使用可能です。

§データ転送命令
機械語ニーモニックフラグ意味
1009hLDX#Y----第1パラメータのアドレスに第2パラメータで指定される値をセットする
100AhLDXY----
100BhLDX[Y]----
100DhLD[X]#Y----
100EhLD[X]Y----
100FhLD[X][Y]----
§算術演算命令
機械語ニーモニックフラグ意味
2002hNEGX--S-パラメータの符号を反転する
2003hNEG[X]--S-
2109hADDX#YCZSV第1パラメータと第2パラメータを加算して結果を第1パラメータのアドレスにセットする
210AhADDXYCZSV
210BhADDX[Y]CZSV
210DhADD[X]#YCZSV
210EhADD[X]YCZSV
210FhADD[X][Y]CZSV
2209hSUBX#YCZSV第1パラメータから第2パラメータを減算して結果を第1パラメータのアドレスにセットする
220AhSUBXYCZSV
220BhSUBX[Y]CZSV
220DhSUB[X]#YCZSV
220EhSUB[X]YCZSV
220FhSUB[X][Y]CZSV
2219hCMPX#YCZSV第1パラメータから第2パラメータを減算してフラグだけを設定する。主に値の比較に使う。
221AhCMPXYCZSV
221BhCMPX[Y]CZSV
221DhCMP[X]#YCZSV
221EhCMP[X]YCZSV
221FhCMP[X][Y]CZSV
§論理演算命令
機械語ニーモニックフラグ意味
3002hNOTX-ZS-パラメータの値をビット単位で論理否定する
3003hNOT[X]-ZS-
3109hORX#Y-ZS-第1パラメータと第2パラメータのビット単位での論理和を第1パラメータのアドレスにセットする
310AhORXY-ZS-
310BhORX[Y]-ZS-
310DhOR[X]#Y-ZS-
310EhOR[X]Y-ZS-
310FhOR[X][Y]-ZS-
3309hANDX#Y-ZS-第1パラメータと第2パラメータのビット単位での論理積を第1パラメータのアドレスにセットする
330AhANDXY-ZS-
330BhANDX[Y]-ZS-
330DhAND[X]#Y-ZS-
330EhAND[X]Y-ZS-
330FhAND[X][Y]-ZS-
3209hXORX#Y-ZS-第1パラメータと第2パラメータのビット単位での排他的論理和を第1パラメータのアドレスにセットする
320AhXORXY-ZS-
320BhXORX[Y]-ZS-
320DhXOR[X]#Y-ZS-
320EhXOR[X]Y-ZS-
320FhXOR[X][Y]-ZS-
3319hBITX#Y-ZS-第1パラメータと第2パラメータのビット単位での論理積をとってフラグだけを設定する。主に値の各ビットのチェックに使う。
331AhBITXY-ZS-
331BhBITX[Y]-ZS-
331DhBIT[X]#Y-ZS-
331EhBIT[X]Y-ZS-
331FhBIT[X][Y]-ZS-
§ジャンプ命令
機械語ニーモニックフラグ意味
4002hJPX----パラメータの指定するアドレスにジャンプする
4003hJP[X]----
410AhJPFXY----第2パラメータが0だった場合第1パラメータのアドレスにジャンプする
410BhJPFX[Y]----
410EhJPF[X]Y----
410FhJPF[X][Y]----
420AhJPTXY----第2パラメータが0でなかった場合第1パラメータのアドレスにジャンプする
420BhJPTX[Y]----
420EhJPT[X]Y----
420FhJPT[X][Y]----
§外部入出力命令
機械語ニーモニックフラグ意味
5009hINX#Y----第2パラメータのポートから第1パラメータのアドレスにデータを入力する
500AhINXY----
500BhINX[Y]----
500DhIN[X]#Y----
500EhIN[X]Y----
500FhIN[X][Y]----
5105hOUT#X#Y----第2パラメータの値を第1パラメータのポートに出力する
5106hOUT#XY----
5107hOUT#X[Y]----
5109hOUTX#Y----
510AhOUTXY----
510BhOUTX[Y]----
510DhOUT[X]#Y----
510EhOUT[X]Y----
510FhOUT[X][Y]----
§その他の命令
機械語ニーモニックフラグ意味
6002hPUSHX----パラメータの値を待避する
6003hPUSH[X]----
6102hPOPX----待避した値をパラメータのアドレスに復帰する
6103hPOP[X]----
7002hSLXCZS-パラメータの値を1ビット左にシフトする
7003hSL[X]CZS-
7102hSRXCZS-パラメータの値を1ビット右にシフトする
7103hSR[X]CZS-
8002hCALLX----パラメータのアドレスのサブルーチンを呼び出す
8003hCALL[X]----
8100hRET----サブルーチンから復帰する
FFF0hHALT----プログラムの終了
0000hNOP----何もしない

3.3 PML疑似命令

Page Top

アセンブリ言語上では疑似命令というものが使える場合があります。これは一見命令風に見えますが機械語命令には翻訳されない命令のことで、アセンブリ言語を記述する際に様々な便利機能を実現するための命令です。

3.3.1 EQU:ラベル定義

Page Top

ラベルを定義するための命令です。

(#)ラベル	EQU	値	(;コメント)
X	EQU	245	;Xというラベルが245という値を持つようになる

ラベルを記述する文字には通常#は使えませんが、EQU疑似命令のときに限って以下のような記述が可能です。

#X	EQU	245	;Xというラベルが245という値を持つようになる

こう記述した場合Xというラベルには即値属性がついて、うっかり即値以外で使おうとしたらエラーが出るようになっています。

例えば下の例ではYにXの値、すなわち245を代入しているように見えますが、実は245番地の値を代入する結果になっています!

	LD	Y	X	←ERROR
	LD	Y	#X	←OK

EQU疑似命令は通常プログラムで使う様々な定数を定義するために使い、これでメモリアドレスを直指定するようなことはないはずです。そこでEQU疑似命令を利用する際は#付きで定義して、使用するときも#付きで使用する、としておくと間違いを減らすことができます。

―――と言いつつ、付属のサンプルプログラムではいきなりEQUでメモリアドレスを定義していますが、これは本書の説明の都合上絶対アドレスで記述していたためです。いわば邪道なので絶対真似しないで下さい。

3.3.2 DW:データセット

Page Top

あらかじめメモリにデータをセットしておく疑似命令です。

(行ラベル:)	 DW	p1,  (p2,  p3, ...)
(行ラベル:)	 DW, p1,  (p2,  p3, ...)		;こうやって全部カンマで区切ってもOK

この疑似命令を使うとプログラムのロード時にその位置にパラメータの値がメモリに順番に格納されていきます。

	DW	10, 10h, 10b, A$

この例では十進法で 10, 16, 2, 65 がメモリにセットされます。

	#P	EQU	100
Q:	DW	#P, Q

こちらの例では#Pのところには100という値が、Qのところにはこの疑似命令のアドレス、すなわち#Pと書かれたメモリアドレスがセットされます。

§パラメータの文字列記法

データに文字列を使いたいような場合、以下のように半角のシングルクォーテーションで囲んで文字列として書くことができます。

	 DW	'今日は朝から夜だった'

これは以下のように書くのと同じです。

	 DW	今$, 日$, は$, 朝$, か$, ら$, 夜$, だ$, っ$, た$

この文字列記法をする場合、文字列内にスペースやタブが入っていても構いませんが、シングルクォーテーション及び半角カンマがあってはなりません。その場合は1.1.4節で説明したようにエスケープ表記を利用して下さい。

	 DW	'I don't have CAT'S EYE'  	←エラーになります
	 DW	'I don\qt have CAT\qS EYE'	←OK
	 DW	'その値は10,000だった'   	←エラーになります
	 DW	'その値は10\c000だった'  	←OK
§DW疑似命令のラベルの利用

DW疑似命令には通常の命令同様に行ラベルが指定できます。

X:	DW	10, 20

例えばこのように記述しておくとXというラベルが10という値の入ったメモリアドレスを指します。

すなわちプログラムで使用するためのメモリをこうして確保して、しかも初期値を入れておくこともできます―――すなわち高級言語における変数定義のようなもので、これがDW疑似命令の最も一般的な利用方法です。

本書のサンプルプログラムではプログラム中で値を入れておくメモリを例えば1000番地とか直接指定していましたが、その番地が本当に空いているかどうか確認するのは面倒な作業です。また初期値設定したい場合はLD命令でいちいち設定する必要がありました。

しかしDW疑似命令のラベルは通常の命令文の行ラベルの仕組みと同じなので、上記の例のXの値はアセンブラが自動的に計算してセットしてくれます。そのためそのアドレスが空いているかどうかいちいち気にする必要がありません。またメモリには同時に10という値が最初にセットされるので、初期値設定の必要がありません。

なお以下のように書けばアドレス直指定の機能が働いて、メモリの250〜254番地に1,2,3,10,12の値がセットされます。

250:	DW	1,2,3,10,12

3.3.3 INCLUDE:ファイル挿入

Page Top

この命令が書かれた場所にパラメータで指定されるファイルを挿入します。

	INCLUDE	filename

この命令を使うと命令の書かれた場所に指定されたファイルを挿入できます。

例えば以下のような内容の二つのファイルを作ります。

<Prog1.pasm>

	ADD	X	Y	;XとYを加算
	SR	X		;Xを2で割る

<Prog2.pasm>

	LD	X	#15
	LD	Y	#25
	INCLUDE	"Prog1.pasm"
	CMP	X	Y
	JPT	>Z	ZF

そしてProg2.pasmを読み込むと、以下のようにINCLUDE疑似命令が書かれた行にProg1.pasmの内容がそのまま、コメントまで含めて挿入されます。

	LD	X	#15
	LD	Y	#25
▼INCLUDE Prog1.pasm
	ADD	X	Y	;XとYを加算
	SR	X		;Xを2で割る
▲END INCLUDE
	CMP	X	Y
	JPT	>Z	ZF

この命令は複数のプログラムで共通の定義やサブルーチンを共有するために便利です。

3.3.4 MACRO:マクロ定義

Page Top

プログラムを「パーツ化」する機能です。

ラベル:	MACRO (仮パラメータ1 (,仮パラメータ2 (, ...))
	マクロソースの記述
	ENDMACRO

定義されたマクロは下記のように記述することで、定義された内容が呼び出された場所に展開されて、仮パラメータが実パラメータに置換されます。

	ラベル	実パラメータ1, 実パラメータ2, ...
§サンプル例

例えば以下のマクロの場合

&IFP_:	MACRO %L, ?L0
	JPT	?L0	ZF	;結果 > 0なら%Lへ
	JPT	?L0	SF
	JP	%L
?L0:
	ENDMACRO

以下のように記述すると

	SUB	X	Y
	&IFP_	>L
	LD	X	#0
>L:	続きの処理

このように展開されます。

	SUB	X	Y
	JPT	*xxxx	ZF	;結果 > 0なら>Lへ
	JPT	*xxxx	SF
	JP	>L
*xxxx:
	LD	X	#0
>L:	続きの処理

3.3.5 PROC:ブロック化

Page Top

ローカルラベルが使えるブロックを定義します。

(行ラベル:)PROC
	
	ENDPROC

上記のようにPROCとENDPROCで囲まれた範囲で定義されたラベルはローカルラベルになります。

例えば以下のようにラベルが定義されているとします。

	#X	EQU	#10	;(1)
FN:	PROC
	#X	EQU	#20	;(2)
	LD	P	#X	;(3)
	LD	Q	#X	;(4)
P:	DW	0		;(5)
	ENDPROC
	LD	P	#X	;(6)
P:	DW	0		;(7)
Q:	DW	0

この例ではXおよびPというラベルが2カ所で定義されています。

すなわちあたかもPROC内で定義されたラベルはそのPROC内でのみ有効として扱うことができます。

3.3.6 UNIT:疑似モジュール化

Page Top

プログラムを擬似的にモジュール化します。

unitname:UNIT
	モジュール内容
	ENDUNIT

上記のようにUNIT疑似命令とENDUNIT疑似命令で囲まれたブロックは疑似モジュールとなります。汎用的なサブルーチンをまとめておきたいような場合に使います。

3.3.7 USES:アクセス指定

Page Top

ユニット内のラベルをアクセス可能にします。

	USES	unit1(, unit2, ...)

プログラムからUNIT内のラベル(主にサブルーチンやグローバルな変数など)にアクセスしたい場合USES疑似命令を使ってユニット名を記述しておくと、そのユニット内のラベルを参照することができるようになります。

3.4 アセンブルエラー

Page Top

3.4.1 アセンブルエラーの表示と修正

Page Top

アセンブルエラーがあった場合メニュー下の情報表示欄に赤太字でエラーの数が表示され、エラーのあった行のコメント欄に以下のようなメッセージが出ます。

[ソースファイル名(エラー行)]エラーメッセージ

エラーを修正するにはエラー行を右クリックしてソースの編集(E)を選択します。ソースファイルが設定されているエディタで開かれて、エディタが行番号ジャンプに対応していればその行にカーソルが飛びます。

そこで修正を行ったあとエディタ上で上書き保存を行い、PMLエミュレータからファイル(F)/読み込み直す(R)を実行すると修正ファイルがロード・アセンブルされます。

3.4.2 エラーメッセージ

Page Top

以下はアセンブルエラーに付随するエラーメッセージです。

§命令が不正です

プログラムの命令はPML命令と疑似命令にあるもの以外は使用できません。

このエラーが出た場合は命令の綴り間違い、ラベルの":"を書き忘れた場合、定義されていないマクロを呼び出した場合などがあります。

§パラメータ数が不正です

PML命令は各々パラメータの必要数が決まっていますが、その数が合わない場合にこのエラーが出ます。

§”ラベル名”は未定義です

引用されたラベルが定義されていないため、値に変換ができません。

PROCのブロック内で定義されているラベル、USES疑似命令でアクセス指定されていないユニット内で定義されているラベルを参照しようとした場合もこのエラーが出ます。

そういったラベルを参照しなければならない場合はネームパスをつけるか、ユニットの場合はUSESでアクセス設定をしておく必要があります。

§数値の評価ができません

EQUでラベルを定義する際の数値の書式に問題があります。

§パラメーターの型が違います

PML命令で利用できないパラメータの組み合わせが使われています。

例えばLD命令の第一パラメータに即値を使用しているような場合です。どういう組み合わせが可能なのかは5.3節を参照して下さい。

また[#X]のように間接参照内に即値を書いたような場合にもこのエラーが出ます。

§行番号が不正です

絶対アドレス指定を行っている場合に、既に定義された領域のアドレスが指定された場合にこのエラーが出ます。

§ラベルの2重定義です

同じ名前のラベルが再度定義された場合このエラーが出ます。

プログラムが小さいうちはいいのですが、大きくなってくるとすぐにラベル名の衝突が起こります。これを防ぐにはPROCやUNIT、マクロのオートラベルなどの機構を利用して下さい。

§ラベルに使えない文字があります

ラベルに使用できる文字は A-Z a-z > ^ _ * です。これ以外の文字が使われていたらこのエラーが出ます。

§パラメータに#がありません

EQUで定義した#付きの即値ラベルを参照する際に#が付加されていません。

§ブロックの対応が不正です

PROC〜ENDPROC、UNIT〜ENDUNITの対応がおかしくなっています。

§ユニット名がありません

ユニット定義を行っているところでユニット名が設定されていません。

§マクロのラベルがありません

マクロ定義をしているところでマクロラベルが設定されていません。

§マクロ名“マクロ名称”が重複しています

引用されたマクロラベルが重複しています。

§マクロパラメータは%か?で始まります

マクロの仮引数が%もしくは?で始まっていません。

§マクロ定義中にマクロ定義はできません

マクロ定義中にさらにMACRO疑似命令が現れました。

前のマクロでENDMACROを書き忘れた場合にもこのエラーになります。

§変なところにENDMACROがあります

マクロ疑似命令がないのにENDMACRO疑似命令が現れました。