ランタイムの作成(その2)


CPM用ランタイムの説明

CPM用ランタイム MCCPM.RUNについて説明します。
ランタイムの作成(その1)の説明にある様に、ランタイムのソースファイルが
C:\CPM\run-srcフォルダにあるものとします。
MCCPM.MAC

;=======================================
;  << Mini Compiler Ver1.0 >>
;    RUN-TIME & FUNCTION for CP/M
;=======================================
BDOS    EQU     0005H         ; BDOSコール番地の定義

;-----------------------
;  Function for CP/M
;-----------------------
INCLUDE MCCPM.FNC             ; ランタイムルーチンと
                              ; 標準関数をインクルード
;-----------------------
;  MC-Initialize
;-----------------------
$MCINIT:                      ; MCで作成されたプログラムが
        RET                   ; 最初に呼び出す

;-----------------------
;  Table for CP/M
;-----------------------
INCLUDE MCCPM.TBL             ; ランタイムルーチンのアドレスと
                              ; 関数テーブル定義をインクルード

        DB  0                 ; 関数テーブルの最後は必ず0とする

        END START             ; この記述でアセンブルされたランタイムの
                              ; 先頭に STARTラベルのアドレスが挿入される
  

MCCPM.FNC

;=======================================
;  << Mini Compiler Ver1.0 >>
;    RUN-TIME & FUNCTION for CP/M
;=======================================
;===============================
;    RUN TIME ROUTINE
;===============================
;-----------------------
;  HL<DE =>TRUE
;-----------------------
$MCLT:                        ; $で始まるラベルがランタイムルーチン
        CALL    CMPSB1
        RET     NC
        INC     HL
        RET

〜 中略 〜

;===============================
;    CPM FUNCTION
;===============================
;-----------------------
;  GETCHR()
;-----------------------
_GETCHR:                      ; _で始まるラベルが標準関数
        LD      C,1
        CALL    BDOS
        LD      L,A
        LD      H,0
        RET

〜 中略 〜

  

MCCPM.TBL

;===============================================
;       << Mini Compiler Ver1.0 >>
;       RUN-TIME & FUNCTION TABLE for CP/M
;===============================================
;-----------------------
;       WORK AREA
;-----------------------
RNDSEE: DW      1992            ; 乱数(_rnd)用ワーク領域
        DW      0C204H

TXTBUF: DB      255, 0          ; 1行入力用ワーク領域
WORK:   DS      255             ; _printf用ワーク領域
CONF:   DS      1

;===============================
;    OBJECT START ADDRESS
;===============================
START:                          ; MCオブジェクトの先頭アドレス。
                                ; このアドレスからコンパイルされた
                                ; オブジェクトが出力されていく。
                                ; 従ってコンパイラはランタイムアドレス
                                ; 関数テーブルを別領域に保存してから
                                ; コンパイルする設計になっている。
;===============================
;    RUN TIME TABLE
;===============================
        DW      $MCLT           ; ランタイムルーチンのアドレスを定義
        DW      $MCGE
        DW      $MCEQ
        DW      $MCNE
        DW      $MCNOT
        DW      $MCNEG
        DW      $MCMULT
        DW      $MCDIVI
        DW      $MCSFTR
        DW      $MCSFTL
        DW      $MCANDB
        DW      $MCAND
        DW      $MCXOR
        DW      $MCORB
        DW      $MCOR
        DW      $MCSTOR
        DW      $MCCALL
        DW      $MCINIT

;===============================
;    FUNCTION TABLE
;===============================
        DB      'GETCHR',0, 0   ; 標準関数の名前とパラメータ数を定義
        DW      _GETCHR         ; 標準関数のアドレスを定義

        DB      'PUTCHR',0, 1
        DW      _PUTCHR

        DB      'PRINTF',0, 15
        DW      _PRINTF

        DB      'SPRINTF',0, 15
        DW      _SPRINF

        DB      'SCANF',0, 15
        DW      _SCANF

        DB      'SSCANF',0, 15
        DW      _SSCANF

        DB      'INKEY',0, 0
        DW      _INKEY

        DB      'BDOS',0, 2
        DW      _BDOS

        DB      'STRLEN',0, 1
        DW      _STRLEN

        DB      'STRCPY',0, 2
        DW      _STRCPY

        DB      'STRCAT',0, 2
        DW      _STRCAT

        DB      'MEMSET',0, 3
        DW      _MEMSET

        DB      'MEMCPY',0, 3
        DW      _MEMCPY

        DB      'MEMCMP',0, 3
        DW      _MEMCMP

        DB      'RND',0, 1
        DW      _RND
  

関数テーブルの説明
関数名名前の終端パラメータ数関数のアドレス説明
PUTCHR01_PUTCHRコンパイル時パラメータ数が1以外だとエラーになる
PRINTF015_PRINTFパラメータ数が15の場合コンパイル時にチェックをしない

関数の追加
関数を追加する場合には、ランタイムファイル名を変えることが必要です。
そうしないと、ソースとランタイムとの互換性が無くなるためです。

MCCPM.MACを元にMCFUNC.MACを作成します。
次に新しい関数 func( ) を追加し、MCFUNC.RUNを作成します。
作業フォルダは C:\CPM\run-src です。
赤字の部分が追加/修正箇所。

MCFUNC.MAC

;=======================================
;  << Mini Compiler Ver1.0 >>
;    RUN-TIME & NEW FUNCTION
;=======================================

;-----------------------
;  Function for CP/M
;-----------------------
INCLUDE MCCPM.FNC

;-----------------------
;  MC-Initialize
;-----------------------
$MCINIT:
        RET

;-----------------------
;    FUNC(a,b)                ; HL=aのb乗
;-----------------------
_FUNC:
        POP     HL            ; 復帰アドレス
        POP     DE            ; 第一引数a
        POP     BC            ; 第二引数b
        PUSH    HL            ; 復帰アドレスをスタックトップに
        LD      H,D
        LD      L,E
FUNC1:
        DEC     BC            ; bをデクリメント
        LD      A,B
        OR      C
        RET     Z             ; bが0になったら復帰
        PUSH    BC
        PUSH    DE
        CALL    $MCMULT       ; HL = HL * DE
        POP     DE
        POP     BC
        JR      FUNC1

;-----------------------
;  Table for CP/M
;-----------------------
INCLUDE MCCPM.TBL

        DB      'FUNC',0, 2
        DW      _FUNC

        DB  0
        END START
  

アセンブル方法
出来上がったランタイムソース(mcfunc.mac)が C:\CPM\run-srcにあることを確認します。

C:\CPM\run-src>tree /f
フォルダ パスの一覧
ボリューム シリアル番号は XXXXXXXX XXXX:XXXX です
C:.
    ASM.BAT
    l80.com
    m80.com
    MCCPM.FNC
    MCCPM.MAC
    mccpm.run
    MCCPM.TBL
    MCCPM32.MAC
    MCFUNC.MAC
    MCMSX.FNC
    MCMSX.HED
    MCMSX.MAC
    MCMSX.TBL
    MCMSX2.MAC

サブフォルダは存在しません
  

下線の部分を入力していきます。

C:\CPM\run-src>cd \cpm

C:\CPM\>env

C:\CPM\>cd run-src

C:\CPM\run-src>asm mcfunc

C:\CPM\run-src>cpm m80 mcfunc=mcfunc/z

No Fatal error(s)

C:\CPM\run-src>cpm l80 mcfunc,mcfunc/n/e

Link-80  3.44  09-Dec-81  Copyright (c) 1981 Microsoft

Data    0103    0626    < 1315>

52497 Bytes Free
[0569   0626        6]

C:\CPM\run-src>ren mcfunc.com mcfunc.run

C:\CPM\run-src>del mcfunc.rel
  

テストプログラム(test.mcf)の作成
出来上がったランタイム(mcfunc.run)をC:\CPM\mcにコピーします。
下記のテストプログラム(test.mcf)をC:\CPM\mcに作成します。
※ソースの拡張子はどのランタイムを使うかの指標になるので、ここでは mcf とします

while 1
    a=0
    printf("a ? ")
    scanf("%d", &a)
    if a == 0 then break endif

    b=0
    printf("b ? ")
    scanf("%d", &b)
    if b == 0 then break endif

    printf("%d ^ %d = %d\n", a, b, func(a,b))
wend
  

テストプログラムの実行
下線部分を入力します。

C:\CPM\mc>cpm mc mcfunc.run test.mcf
*** Mini Compiler (Ver 1.0) ***
Compile complete.

C:\CPM\mc>run test

C:\CPM\mc>cpm -w1 test.com
a ? 3
b ? 5
3 ^ 5 = 243
a ? 5
b ? 2
5 ^ 2 = 25
a ?     ENTERキーだけの入力でプログラム停止

C:\CPM\mc>
  

「クロス開発環境で..」の説明の中にでてくる mc.zip 内のバッチファイルに不具合がありました。
ここからダウンロードし直してください。