Toopoをねらえ! Vz講座


オープニング
「マクロはC言語ライク」
■■変数
■■構造化構文
「マクロは中間コードの直書」



オープニング
た○や
「ねぇ,おねえさま. Vz ってなんですか?」
コーチ
「あまいぞっ,た○や.いぃかぁ,よぉく聞け.Vz とはそもそもなつかしのPC-98 用につくられたフリーのテキストエディッタ EzEditer を改良して,ビレッジセンターが販売していたものだ.当時,EzEditer はアセンブラで作成されていて,そのファイルサイズが,ちょうど 9800 Kbyte だったことも有名だ.市販ソフトになってVzと改名され,機能拡張用のマクロ言語を搭載するようになって,その拡張性の高さから非常に人気を博したエディッタだ.よぉく覚えておけ.」
あ○の
「そうよ,た○やさん.まだまだあまいわね.そんなことも,知らないのでは,とてもガン○スターには乗せられないわ.これから特訓よ」
た○や
「ふえぇぇぇぇ....」

「マクロはC言語ライク」

■■変数
コーチ
「どーだ,た○や.マクロの勉強は進んでいるか?」
た○や
「はい,コーチ.『VzマクロはC言語ライクな言語体系をしており,初心者でも簡単にマクロを作成することができます』,みたいなことを書いてありました.それなら私みたいなおっちょこちょいでも,なんとかやれるかもしれません」
コーチ
「ほう,おまえもC言語を知っていたのか.ちょうどいい,マクロのC言語ライクなところをあげてみろ」
た○や
「はいっ!たとえば,『Vzマクロで使用できる変数は,16bit整数,SJIS格納用の文字変数,ポインタ,配列,文字列へのポインタなどです』などと,書いてあります.C言語のchar が w_char になっていて,使いやすそうですね.さすが,エディッタマクロ,文字の扱いはしやすそうです.ただ,『ローカル変数はなく,グローバル変数のみです』とありました.ちょっと残念ですけど,変数名を慎重に扱うようにすれば,大丈夫だと思います.」
コーチ
「あーまーいーぞっ!た○や.いいか敵をもっとよく見てみろ.16bit 整数,8086上でのnear ポインタ,同じく文字列へのポインタ,配列も変数自体は配列の先頭へのポインタ,そしてSJIS文字変数は 16bit サイズの変数だ.つまり使える変数の全てが 16bit サイズとなる.さらに,ローカル変数がないと言うのは結局,全部 16 bit サイズのレジスタだということだ.変数の種類などもともと存在しない!」
た○や
「ひぇぇぇ..」
あ○の
「そうよ,た○やさん.Vzマクロには変数なんて高級な物はないの.演算子によってアクセスされるときのレジスタの使われ方によって,区別しているだけなのよ.たとえば,変数 a, b を,b = a + 2などと使うときは,16bit 整数.ポインタ演算子 '.' を使って a.0 の様にアクセスすると,a は near ポインタとなり,そこからのインデックス 0 番目のアドレスの 8 bit の内容を評価するのよ.こんな所で,騙されてはいけないわ」
た○や
「さっすが,おねえさま.ちゃんと,騙されずにマクロを知ってらっしゃるわ.やっぱり天才ですね.」
あ○の
「ちがうわ.私もはじめは分からなかったわ.でも,分るように努力するの.そうすることによって,今の自分を作り上げてゆくのよ」
た○や
「じゃ,努力の天才なんですね!」
あ○の
「.....」

■■構造化構文
あ○の
「てへへ.いきなり怒られてしまいましたけど,次は大丈夫です.Vzマクロには構造化構文があるんです.いわゆる,連接,if文,for文が存在します.また switch構文なんかもあって,ちゃんとした構造化プログラミングができるようになっています.これはちゃんと勉強しておきました.また,これはスパゲッティプログラミングの現況ともなりますが,goto文もサポートされています.goto文てたまにつかえると便利なときがありますね」
コーチ
「まだまだあまいぞ,た○や.いいか次に上げるif文とfor文をよぉく見てみろ」

if 文   : ( condition )?{ 文 }
if-else文 : ( condition }?{ 文 }?{ 文 }
for文   : ( counter ){ 文 }

た○や
「あれれぇ?なんだか似たような文がならんでいますね?」
コーチ
「そーだ.これらは非常によく似ている.C言語しか知らないおまえにはわからんだろうが,これらの中には,Vz マクロ関数が含まれている.それを示すと,こーなる.」

(式)  : Vz内部に特別に存在する,評価レジスタに,
     「式」を評価した値を代入する.
?{文}  : 内部評価レジスタの値を参照し,それが 0以外なら次に続く一つの文,
     またはブロックを実行し内部評価レジスタを論理反転する.
     0 ならば次に続く一つの文,またはブロックをスキップし,
     内部評価レジスタを論理反転する.
{    : そのブロックが始る位置に,ループ専用の内部ラベルレジスタに,
     そのロケーションカウンタを保存する.また,内部評価レジスタの値を,
     内部カウンタレジスタに転送する.
}    : 内部カウンタレジスタの値を1だけデクリメントする.その後,
     もし内部カウンタレジスタのあたいが0 になっていなければ,
     内部ラベルレジスタの指し示すアドレスにジャンプする.

コーチ
「いいかぁ,上にでてきた3つの内部レジスタ(評価,ラベル,カウンタ)は,すべてVzシステムに固有のアドレスと 16bit メモリ空間が割当てられており,それぞれ1つ文だけしかレジスタが存在しない.このため,以下に示すような2重ループをすることができない.なぜなら,そんなことをすれば,2重の内側のブロックが,外側のブロックがつかっていた内部レジスタの値を,勝手に上書きするからだ」

ループの入れこ : ( counter1 ){ (counter2){ 文 } }
                     ^^^ ここで内部レジスタが上書きされる.

コーチ
「ただし,if文の入れこは大丈夫だ.なぜなら,以下に示すように,cond1 のときの内部評価レジスタは,すぐ次の "?" コマンドですぐに評価され,cond2 の評価時にはもう使用することはないので上書きしてもいいからだ」

if文の入れこ :  ( cond1 )?{ ( cond2 )?{文} }
                ^^^ cond1 の評価値を代入した内部評価レジスタが
                  評価される

コーチ
「また,実は,2重ループも実現することができる.Vzの内部レジスタのアドレスは,すでに幾多の人々の手により解析されている.そのため内部カウンタレジスタのアドレスを 0xA000 とすると,以下のように,スタックへのプッシュ・ポップを利用して,2重ループを構成することが可能だ.」

<予備知識>
a[, or 10[, - 変数や定数の内容をプログラムスタックへプッシュ
a],     - スタックからポップし,その値を変数へ代入.
a..b     - ポインタ a から,b インデックスの分だけ移動したアドレスの中身の
        値を取出す.( "." は 8 bit アクセス,".." は 16bit アクセス)


( counter )?{ 
	0xA000..0[, 		; 内部カウンタレジスタ(16bit)の値をスタックへプッシュ
	( counter2 )?{
		文
	}					; カウンタレジスタをデクリメント&ループ先頭へのジャンプ
	0xA000..0],			; 内部カウンタレジスタ(16bit)の値をスタックからポップ
}						; カウンタレジスタをデクリメント&ループ先頭へのジャンプ

た○や
「う〜ん,こんな感じのプログラム,どこかで見たような気がするんですけど....」
コーチ
「ん? なかなか勘が鋭いな.実は,上のアルゴリズムをアセンブラで記述すると以下のようになる」

		mv word ptr [dx][0], 13		;カウンタの値をセット
		mv ax, [dx][0]
		mv cx, ax
loop1:	mv word ptr [dx][0], 5		;カウンタの値をセット
		mv ax, [dx][0]
		push cx						;loop1カウンタの値をプッシュ
		mv cx, ax
loop2:	statement
		    .
		    .
		statement
		jr nz loop2
		pop cx						;loop1 カウンタの値をポップ
		jr nz loop1

た○や
「えぇ!? なんでアセンブラなんですか? しかも,ほとんどマクロで書いたのとおんなじ.(ぐるぐる)」
あ○の
(さっそうと登場)「そうよ,た○やさん.これは,アセンブラのテクニックの1つよ.でも,これくらいで,あせっていてはだめね.ちなみに Z80 では,ちょうど DJNZ がこれにあたるわ 」
た○や
「おねぇさま!でも,さっきまで構文はC言語ライクだと思っていたのに,なんでいきなりアセンブラのプログラムになるんですか?」
あ○の
「それは,C言語と偽っていた方が,壁が低いし,初心者の方でも気軽に扱えるからよ.でも,中身はアセンブラなの.た○やさんもよく気を付けてね」
コーチ
「そうだ,た○や.敵は火星から月まで3分で到達する.甘く見てはいかんぞ」
た○や
「ふぇぇぇ...」
コーチ
「ちなみに,マクロにはgoto文もあるといっていたが,実はそれだけではない.昔のBASIC にあった,算術goto 文もサポートされているぞ.これを使えば,ちょっと見ただけでは,どのサブルーチンに跳ぶのかわからない,というようなプログラムを書くことも可能だ.この部分を書取り100回やっておけっ」

■サブルーチン,関数
■■サブルーチンへのジャンプ
■■関数呼出しと戻り値の処理
■■ロケーションカウンタ
「マクロは中間コードの直書」
■高級テクニック
■■ax, bx, cx, dx んどの 8086 レジスタへのアクセス
■■システムコール
■■デバドラと通信
■■インラインアセンブラ