第32章
MSX-BASICのBLOAD用のバイナリ
MSX-BASICは、マシン語のファイルをBLOADで読み込んで実行できます。この章では、A:\TATARA\EXAMPLES\BINARYにある例、BINARYを作ります。そのようなファイルを作ってBASICから実行し、そのあとで、BASICのメモリのどこにマシン語のファイルを安全に置けるかを見ます。
32.1 この例
BINARYは、1つのソースBEEP.ASと、そのBUILD.BATからなります。プログラムは1行を表示し、MSXのブザーを鳴らして、BASICに戻ります。これは.COMのプログラムではありません。BASICが実行するときにはMSX-DOSがないので、MSXのROMにあるルーチン、つまりBIOSを使って表示します。TANRENは、これをBLOADのヘッダー付きで書き出し(26.4節)、それによって.BINのファイルになります。
32.2 ソース
; BEEP.AS - a machine-code file for MSX BASIC. ; ; BLOAD"BEEP.BIN",R loads this and runs it. The seven bytes BASIC ; reads first - FEh, the first address, the LAST address, and the ; address to call - are written by TANREN when /B is given, and ; nothing else makes a file a .BIN. ; ; ASEG and ORG: the code is at a fixed address and the linker moves ; nothing. It has to be, because BASIC loads it where the header says ; and does not relocate anything. ; ; There is no MSX-DOS here, so the printing is the BIOS. include bios.inc ; CHPUT, BEEP, and every other ; MAIN ROM entry include ascii.inc ; CHR_CR and CHR_LF aseg org 8000h ; above BASIC in a 64 KB machine start: ld hl,msg loop: ld a,(hl) or a jr z,done push hl call CHPUT pop hl inc hl jr loop done: call BEEP ret ; back to BASIC, which is waiting msg: db "Loaded by BLOAD, run from BASIC.",CHR_CR,CHR_LF,0 end start ; the address the header carries
- ASEGとORGは、コードをアブソリュート・セグメントの8000hに置きます(10章)。ファイルはヘッダーにあるアドレスに読み込まれ、TANRENはソースが示すアドレスをそのまま使います。
- ループは、最後の0のバイトに達するまで、Aの文字を表示するBIOSのルーチンCHPUTで、メッセージを1文字ずつ表示します。CHPUTとBEEPのアドレスは、BIOS.INCにあります。
- BEEPは、ブザーを鳴らす別のBIOSのルーチンで、RETで BASICに戻ります。
- ENDの行はstartを示します。TANRENはこれを、呼び出すアドレスとしてヘッダーに入れます(26.5節)。
32.3 作る
rem BUILD.BAT - EXAMPLE: BINARY rem rem A .BIN for MSX BASIC instead of a .COM for MSX-DOS. Two things rem make the difference: rem rem ASEG and ORG the code is at a fixed address, not relocatable rem TANREN /B the seven-byte BLOAD header goes in front of it rem rem The address BASIC calls is the one on the END line of the source. rem Without /B the same link writes the bytes and no header, which is rem what a ROM needs - see the ROM example. rem rem To run it, from BASIC: BLOAD then the file name in quotes, ,R rem The headers are in A:\TATARA\INCLUDE and are not copied here. rem TATARA is rule 3 of the include search - see the DIRS example. rem CHANGE THE PATH BELOW if you put the tree somewhere else. set TATARA=a:\tatara\include echo === Assembling tatara /q beep.as beep.tro echo === Linking, with a BLOAD header tanren /q /b /o:beep.bin beep.tro echo === Done. BEEP.BIN is 7 bytes of header and the rest is code. set TATARA=
A:\TATARA\EXAMPLES\BINARY>build === Assembling === Linking, with a BLOAD header === Done. BEEP.BIN is 7 bytes of header and the rest is code.
/Qなしで実行すると、TANRENの要約で書き出したものがわかります。
A:\TATARA\EXAMPLES\BINARY>tanren /b /o:beep.bin beep.tro ... 1 modules, 6 records, ends at EOF. Wrote BEEP.BIN, 8000-8035 (54 bytes), BLOAD header, entry 8000.
プログラムは54バイトで、ファイルは61バイトです。最初の7バイトがヘッダーです。
FE 00 80 35 80 00 80
FE、続いて最初のアドレス8000h、最後のアドレス8035h、呼び出すアドレス8000hで、どれも下位バイトが先です。そのあとにプログラムが続きます。21 13 80はld hl,msgで、メッセージは8013hにあります。
32.4 BASICから実行する
MSX-BASICで、例のディレクトリから、,Rを付けてBLOADすると、ファイルを読み込み、その開始アドレスを呼び出します。
Ok BLOAD"BEEP.BIN",R Loaded by BLOAD, run from BASIC. Ok
行のあとにブザーが鳴り、RETでBASICに戻って、BASICがOkと表示します。
32.5 ファイルを置ける場所
BASICが動いている間、8000hより下のアドレスにはBASICのROMとBIOSがあるので、BLOAD用のファイルは、その上のRAMに置く必要があります。しかし、BASICもそのRAMを使います。メモリの中のBASICのプログラムは 8000hのすぐ上から始まり、そのあとに変数が続きます。上の例がうまくいったのは、メモリにプログラムがなかったからです。プログラムがあると、同じファイルがそれを上書きします。
list 10 PRINT "hello" Ok bload"beep.bin",r Loaded by BLOAD, run from BASIC. Ok list 46974 INSTRMAXTRON 25697 ed by BLOAD, run from BASIC.501WAIT_VPOKE=^KILLL<0MERGEeMAXO<>41933;+;(3:( ...
マシン語はそれでも実行されて1行を表示しましたが、BASICのプログラムは消えています。LISTは、マシン語をプログラムのように読んで表示し、そのあとマシンは反応しなくなります。
CLEARを使うと、ファイルに必要なメモリからBASICを遠ざけられます。CLEAR 200,&HC000は、BASICに文字列用の200バイトを与え、さらにここで大事なことに、C000hから上のメモリを使わないようにBASICに伝えます。そうすれば、図32.1のように、C000hに置いたファイルは BASICの邪魔になりません。
BEEPC.ASは、BEEP.ASのORGを変えたものです。
aseg org 0C000h ; above the CLEAR address
Ok clear 200,&hc000 Ok bload"beepc.bin",r Loaded by BLOAD, run from BASIC. Ok
CLEARは、最初のBLOADの前、そしてBASICのプログラムを入力したり読み込んだりする前に実行してください。CLEARは変数も消すからです。マシン語を使うBASICのプログラムは、ふつうCLEARの行で始まり、そのあとで自分のファイルをBLOADします。マシン語が多いほど、CLEARに与えるアドレスを低くする必要があり、BASICに残るメモリは少なくなります。
32.6 試してみること
次のファイルは例には含まれていません。BUILD.BATと同じようにTATARAを設定して、例のディレクトリに作ってください。
32.6.1 コードをTANRENに置かせる
モジュールはASEGとORGを使わなくてもかまいません。BEEPR.ASは同じプログラムを標準のコード・セグメントに置いたもので、TANRENが/P:でそれを置きます(24.3節)。
; BEEPR.AS - the same code, relocatable: TANREN /P: places it. include bios.inc include ascii.inc cseg start: ld hl,msg loop: ld a,(hl) or a jr z,done push hl call CHPUT pop hl inc hl jr loop done: call BEEP ret msg: db "Relocated by TANREN /P:.",CHR_CR,CHR_LF,0 end start
A:\TATARA\EXAMPLES\BINARY>tatara /q beepr.as beepr.tro A:\TATARA\EXAMPLES\BINARY>tanren /b /p:c000 /o:beepr.bin beepr.tro ... Wrote BEEPR.BIN, C000-C02D (46 bytes), BLOAD header, entry C000.
こうすれば、同じソースをどのアドレス用にもリンクでき、複数のモジュールからなるプログラムを全体としてまとめて置けます。
32.6.2 USRで呼び出す
,Rなしでは、BLOADはファイルを読み込むだけです。DEFUSRがマシン語のルーチンのアドレスを示し、USRがそれを呼び出します。
Ok clear 200,&hc000 Ok bload"beepr.bin" Ok defusr=&hc000 Ok a=usr(0) Relocated by TANREN /P:. Ok
こうすれば、ルーチンを読み込み直さずに、プログラムが必要なだけ何度でも呼び出せます。
32.6.3 /Bを外す
/Bなしでリンクすると、ファイルは同じ54バイトで、ヘッダーはありません。
A:\TATARA\EXAMPLES\BINARY>tanren /o:beepraw.bin beep.tro ... Wrote BEEPRAW.BIN, 8000-8035 (54 bytes), entry 8000.
FEで始まらないので、BLOADはこれを受け付けません。
Ok bload"beepraw.bin",r Bad file mode Ok