せっかく動いたPL/M。もう少し遊んで見る。
・よくあるHello worldの例
Unofficial CP/M(http://www.cpm.z80.de/source.html)の「EARLY CP/M SOURCE」内のBDOS.PLMやCCP.PLMを参考に作成
===========================================
100H: /* [1] */
DECLARE BDOS LITERALLY '05H';
MON1: PROCEDURE(F,A); /* [2] */
DECLARE F BYTE,
A ADDRESS;
GO TO BDOS;
END MON1;
DECLARE
CR LITERALLY '13',
LF LITERALLY '10';
PRINTCHAR: PROCEDURE(CHAR);
DECLARE CHAR BYTE;
CALL MON1(2,CHAR);
END PRINTCHAR;
CRLF: PROCEDURE;
CALL PRINTCHAR(CR);
CALL PRINTCHAR(LF);
END CRLF;
PRINT: PROCEDURE(A);
DECLARE A ADDRESS;
CALL MON1(9,A);
END PRINT;
RET$CPM: PROCEDURE; /* [3] */
CALL MON1(0,0);
END RESET;
HELLO:
DO;
CALL PRINT(.'HELLO WORLD$'); /* [4] */
CALL CRLF;
CALL RET$CPM; /* [3] */
END HELLO;
EOF /* [5] */
=========================================
・注意点
[1]スタートアドレスが必要。ないと0スタート
[2]入出力は自前でBDOSを呼ぶ
昔からCP/MのBDOS Callが、CとDEにパラメタを入れるのが不思議だったのだが、PL/Mはそれに合ったコードを出す
(初期のCP/MはPL/Mで書かれていたようなので、卵が先か鶏が先かなのかもしれない)
[3]コンパイルしたコードの最後は、EI HALTになる
これはCP/Mから実行する場合は困る。そこでRET$CPMというCP/Mに戻るコードを加えた。
[4]文字はUpperCaseのみ。例え文字列であってもLowerCaseはだめ(Hello worldとは書けない)
[5]最後にEOFが必要
[6]コンパイル時のエラーは、fort.12の最後を見ること。「1 PROGRAM ERROR」とか出ている。
・コンパイル結果と実行結果
>ddt HELLO.HEX
DDT VERS 1.4
NEXT PC
0161 0000
-l100,160
0100 LXI SP,01F8
0103 JMP 0144
0106 LXI H,01F9 ;MON1 固定なので再帰は出来ない
0109 MOV M,C ;第1引数はBYTEで1バイト
010A INR L ;INX HではないのはHLは奇数なことを見越した最適化かな
010B MOV M,E ;第2引数はADDRESSで2バイト
010C INX H
010D MOV M,D
010E JMP 0005 ;BDOS CALL
0111 RET
0112 LXI H,01FD ;PRINTCHAR
0115 MOV M,C ;第1引数はBYTEで1バイト メモリ経由でEレジスタへ
0116 MVI C,02
0118 MOV E,M
0119 MVI D,00
011B CALL 0106
011E RET
011F MVI C,0D ;CRLF
0121 CALL 0112
0124 MVI C,0A
0126 CALL 0112
0129 RET
012A LXI H,01FE ;PRINT
012D MOV M,C ;第1引数はADRESSで2バイト メモリ経由でDEへ
012E INX H ;HLは偶数なのでINX H ?
012F MOV M,B
0130 MVI C,09
0132 DCR L
0133 MOV E,M
0134 INR L
0135 MOV D,M
0136 CALL 0106
0139 RET
013A MVI C,00 ;RET$CPM
013C MVI E,00
013E MVI D,00
0140 CALL 0106
0143 RET
0144 JMP 0153 ;メインルーチンへ
0147 MOV C,B
0148 MOV B,L
0149 MOV C,H
014A MOV C,H
014B MOV C,A
014C ??= 20
014D MOV D,A
014E MOV C,A
014F MOV D,D
0150 MOV C,H
0151 MOV B,H
0152 INR H
0153 LXI B,0147 ;メインルーチン 0x147は DB 'HELLO WORLD$'のアドレス。
0156 CALL 012A ;PRINT
0159 CALL 011F ;CRLF
015C CALL 013A ;RET$CPM
015F EI ;ここへは戻らない
0160 HLT
0161
-
>load HELLO.HEX
FIRST ADDRESS 0100
LAST ADDRESS 0160
BYTES READ 0061
RECORDS WRITTEN 01
E>HELLO
HELLO WORLD
RunCPM Version 5.3 (CP/M 2.2 60K)
※コメント投稿者のブログIDはブログ作成者のみに通知されます