マクロアセンブラを使ったUTILS実装

某所の資料テクニカルハンドブック
に書かれているUTILS機能を持つアセンブラをマクロを用いて書いてみる。このマクロとアセンブラだけで
DOSコマンド上で動くコマンドを作成できる。Cのライブラリを作成するときにも便利。Cとの違いに注意。


util.asm
;マクロを用いたutilsアセンブラルーチン群。
;
	.area _ASMCODE

;DOSファンクションコールを用いて一文字出力する
;引数:chcode
.macro putchar chcode
	push	af
	push	bc
	push 	de
	push	hl
	
	ld		e,chcode	;char code
	ld		c,#0x02		;function #02
	call	0x0005		;function call
	
	pop		hl
	pop		de
	pop		bc
	pop		af
.endm

;数値を2桁16進に変換してDOS画面表示する
;引数:num
.macro puthex num,?puthx1,?puthx2
	
	ld		a,num
	push	af			;一桁目をプッシュ
	rr		a
	rr		a
	rr		a
	rr		a
	push	af			;二桁目をプッシュ
	
	and		#0x0f		;一桁目の処理
	cp		#10
	jr		c,puthx1
	add		a,#'A-10-'0

puthx1:
	add		a,#'0
	putchar	a

	pop		af			;二桁目の処理
	pop		af
	;push	af
	
	and		#0xf		;数値を16進範囲でマスク
	cp		#10			;10で比較
	jr		c,puthx2	;もし10以下ならばputhx2にジャンプ
	add		a,#'A-10-'0	;16進英字のコード処理
	
puthx2:
	add		a,#'0		;数値文字コードの処理
	putchar	a
	;pop	af

.endm


;2桁の16進文字列から整数へ変換
;引数:address
;HL=戻り値
.macro	hex2int	address

	ld		hl,#0
	ld		de,#address

	push 	af
	push 	de
	call	sub
	pop		de
	pop		af
	

sub:
	ld		a,(de)		;文字列ポインタから値を読み
	inc 	de			;ポインタ加算

	;sub	#48
	sub 	#'0			;文字を数値に変換
	ret		c			;文字列終端検出時に戻る
	
	cp		#10
	jr		c,jump1		;HEX数字範囲検出
	;sub	#17
	sub		#'A-'0
	ret		c

	cp		#6			;HEX文字数字範囲検出
	ret		nc

	add		A,#10		;hex2intの整数加算処理
jump1:
	add		hl,hl		;上位桁へのシフト
	add		hl,hl
	add		hl,hl
	add		hl,hl
	or		l
	ld		l,a

	jr		sub

.endm


;DOSコマンド上の引数要素(ARGS)を文字列バッファへ取り出す
;引数:index=argsの要素番号, buffer=コピー先文字列のアドレス
;DE=文字列バッファのアドレス
.macro getarg	index,buffer,?skiparg,?skip1,?skip2,?copyarg,?copy1,?noarg,?exit,?termchk
	push	af
	push	bc
	push	hl
	
	ld		c,index			;ARGSのパラメータ要素指定
	ld		hl,#0x0080		;ゼロページ領域のポインタ指定cpmのargsは0x0080から始まるが先頭の1byteに文字数の長さ
	ld		b,(hl)			;2byte目には空白を示す0x20が入っているため実質的に文字列は0x0082から始まる
	inc		hl

	inc		b			;ARG文字数=Bレジスタ
skiparg:				;コマンド引数なしの時の判定処理
	dec		b
	jr		z,noarg		;

skip1:
	ld		a,(hl)		;ARGの先頭の一つの文字列の検出
	inc		hl
	call	termchk		;文字列の終端確認
	jr		nz,skip1

skip2:
	ld		a,(hl)		;ARGの後続文字列の検出
	inc		hl
	call	termchk
	jr		z,skip2		;文字列の終端確認

	dec		hl
	dec		c			;ARGS要素の指定要素値に達したか判定
	jr		nz,skiparg


copyarg:
	ld		de,buffer	;文字列コピー先バッファアドレスの指定

copy1:
	ld		a,(hl)		;ARGSから文字列をバッファへ複写処理
	ld		(de),a
	inc		hl
	inc		de
	call	termchk		;文字列終端検出
	jr		nz,copy1

	dec		de			;文字列最後にCPMの終端記号を追加
	ld		a,#'$
	ld		(de),a
	ld		de,buffer	;バッファアドレスを返して戻る
	jr		exit		;終了

termchk:
	cp		#0x09			;文字列終端チェックサブルーチン
	ret		z
	
	cp		#0x0d
	ret		z
	
	cp		#0x20			;' '
	ret		z
	
	cp		#0x3b			;';'
	ret		z
	
	ret

noarg:
	ld		de,buffer	;引数なしの場合は終端記号のみで戻る
	ld		a,#'$
	ld		(de),a
	
exit:
	pop		hl
	pop		bc
	pop		af
	;ret				;元のコードはサブルーチンなのでマクロではコメントアウト

.endm


;指定アドレスのメモリ内容を16進データとしてDOS画面に一行ダンプする
;引数:address
.macro	dump8b	address,?dumpln,?dump1,?dump2,?dump3,?dump4

dumpln:
	ld		hl,address

	push	hl			;アドレスを保存
	ld		b,#16			;桁表示用のカウンタ設定(オリジナルは8桁)

dump1:
	ld		a,(hl)		;16進ダンプ開始
	inc		hl
	;call	puthex
	puthex	a   ;マクロ内部からマクロを呼ぶ
	
	ld		a,#0x20		;' '
	;call	putchar
	putchar	a
	djnz	dump1		;Bカウンタ以内で繰り返し

	pop		hl			;再度アドレスを取り出す
	ld		b,#16			;桁カウンタ設定(オリジナルは8桁)

dump2:
	ld		a,(hl)		;以下ASCII文字表示
	inc		hl
	cp		#0x20
	jr		c,dump3		;制御コードの場合ジャンプ
	cp		#0x7f
	jr		nz,dump4	;ASCII,カナ文字の場合ジャンプ

dump3:
	ld		a,#0x2e		;'.'
dump4:
	;call	putchar
	putchar	a
	djnz	dump2		;Bカウンタ以内で8文字処理の繰り返し
	
	ld		a,#0		;空白と改行
	;call	putchar
	putchar	a

	ld		a,#0x0a
	;call	putchar
	putchar	a

	;ret

.endm




sdasアセンブラのutilマクロを利用したサンプル例。マクロアセンブラはこのようにして使う。マクロの引数は
レジスタや即値なので高級言語やCと引数のとりかたが若干違う。
マクロはincludeしているが短い場合はソース中の先頭に貼ってもよい。

	.area _ASMCDOE
	.include /util.asm/

main:
	putchar	a			;レジスタAの文字コード表示
	putchar	#'B			;即値で文字Bを表示
	putchar #'\n		;改行

	puthex	c			;レジスタCの内容を2桁16進画面表示

	hex2int	str1		;str1の文字列の2桁16進を整数にしてHLへ

	getarg	#1,buff		;ARGSの1番目の文字列をbuffへコピー
	
	dump8b	addr		;addrのメモリ内容をダンプ表示

	ret					;DOSなので最後に必ずRET



アセンブル例

>sdasz80 -o util.rel util.asm
>sdld -b _ASMCODE=0x100 -i util.ihx util.rel
>makebin -s 8192 util.ihx > util.bin
>cscript bin2com.vbs util.bin (先頭255バイト削除コマンド)

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2017年05月05日 01:54
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。