2014年9月13日土曜日

BDS C の使い方 - マシン語とのリンク(インテルニーモニック)

>BDS C の使い方 - 目次

必要なファイルの準備


ASM.COM

C 言語から使えるマシン語の関数を使用するために、CP/M 標準のアセンブラ ASM.COM が必要になります。The Unofficial CP/M Web site で入手できる、CP/M 2.2 BINARY (cpm22-b.zip) 等から ASM.COM をコンパイラのあるフォルダにコピーしておきます。
(CP/M は、現在ライセンスを保有している Lineo社 の許可を受けて "Unofficial CP/M Web Site" で配布されていますが、"Unofficial CP/M Web Site" 以外で再配布しても良いとは書かれていないようでした。)

CASM.COM と CLOAD.COM

BDS C 用の関数を作成する ASM.COM 用のプリプロセッサ CASM.COMASM.COM が出力した HEXファイルをバイナリファイルに変換する CLOAD.COM が必要なので、BDS C のアーカイブに含まれているソースコードから BDS C でコンパイルして作成します。
bdsc160\work\CASM.C
bdsc160\work\CLOAD.C
をコンパイラのあるフォルダにコピーして、windows のコマンドプロンプトで以下のようにコンパイルしました。
>cpm cc casm -e4b00
BD Software C Compiler v1.60  (part I)
  20K elbowroom
BD Software C Compiler v1.60 (part II)
  24K to spare

>cpm clink casm
BD Software C Linker   v1.60

Last code address: 4AF5
Externals start at 4B00, occupy 1285 bytes, last byte at 5D84
Top of memory: FDFF
Stack space: A07B
Writing output...
  36K link space remaining 

>cpm cc cload
BD Software C Compiler v1.60  (part I)
  40K elbowroom
BD Software C Compiler v1.60 (part II)
  38K to spare

>cpm clink cload
BD Software C Linker   v1.60

Last code address: 1FCB
Externals start at 1FCC, occupy 0148 bytes, last byte at 2113
Top of memory: FDFF
Stack space: DCEC
Writing output...
  47K link space remaining

BDS.LIB

アセンブラで書いた関数から、引数のアクセス等 BDS C の機能を利用するためのヘッダファイル BDS.LIB が BDS C のアーカイブに含まれているので、bdsc160\work\BDS.LIB をコンパイラのあるフォルダにコピーしておきます。

準備はこれで終了です。


アセンブラで関数の作成


試しにアセンブラで簡単な関数を作成してみます。
インテルニーモニックで下のソースコードを書いて TESTFUNC.CSM という名前で保存しました。
; BDS C でマシン語とのリンクのテスト
; インテルニーモニック


        INCLUDE "BDS.LIB"       ; アセンブラから c.ccc (ccc.asm) 
                                ; にアクセスするのに必要なヘッダファイル
        
        
        FUNCTION        testfunc        ; int testfunc(int a, int b)
                                        ; a + b の結果を返す関数
        CALL    ma1toh          ; 1つ目の引数を HLとAレジスタに入れる
        XCHG                    ; EX DE,HL
        CALL    ma2toh          ; 2つ目の引数を HLとAレジスタに入れる
                                ; 同じように 7番目の引数まで取り込める
        DAD     D               ; HL=HL+DE
        RET                     ; HL が返り値になる
        ENDFUNC
        
        
        FUNCTION        di      ; 割り込み禁止
        DI
        RET
        ENDFUNC
        
        
        FUNCTION        ei      ; 割り込み許可
        EI
        RET
        ENDFUNC

        END
FUNCTION ~ ENDFUNC 擬似命令で囲まれた部分が、C言語から見える一つの関数になります。
C 言語から引数がスタックに積まれて関数がコールされ、関数は HL レジスタに返り値を入れてリターンします。関数では BC レジスタ以外のレジスタを破壊しても問題ありません。
マニュアルの「Chapter 2 CRLファイルの構造」「Chapter 8.1 CASM プリプロセッサ」に説明があるので、ざっと読んでおきます。

アセンブル

windowsのコマンドプロンプトで以下のようにアセンブルしました。
>cpm casm test\TESTFUNC

>cpm asm test\TESTFUNC

>cpm cload test\TESTFUNC
これで、TESTFUNC.CRL が作成されます。


C 言語から使ってみる


作成したアセンブラの関数を、C 言語から使ってみます。下のソースコードを asmfunc.c という名前で作成しました。
#include <stdio.h>

main()
{
    int a,b,c;
   
    a=123;
    b=456;
    c=testfunc(a,b);    /* アセンブラで書いた関数を呼び出し */
   
    printf("%d + %d = %d\n",a,b,c);
}
コンパイルして TESTFUNC.CRL とリンクさせます。
>cpm cc test\asmfunc.c                        コンパイル

>cpm clink test\asmfunc test\TESTFUNC         asmfunc と TESTFUNC のリンク

>cpm test\asmfunc                             実行
123 + 456 = 579
無事動きました。

割り込みを禁止/許可する関数も作ったので、MSX の VDP を直接アクセスして縦スクロールしてみるプログラム msxvdp.c を作ってみました。
/*
    BDS C でMSXのI/Oを直接操作でVDPをいじってみる
*/

#define VDP 0x98

scrool(line)
int line;
{
    di();
    outp(VDP+1,line);
    outp(VDP+1,0x80+23);
    ei();
}

main()
{
    char count;
   
    di();               /* 割り込み禁止 */
    outp(VDP+1,0);      /* VRAM アドレスセット */
    outp(VDP+1,0x40);   /* VRAM アドレスセット 書き込み指示 */
    ei();               /* 割り込み許可 */
   
    for(count=0xFF; 0!=count; count--)
    {
        outp(VDP,count);    /* VRAM 書き込み 自動インクリメント*/
    }
   
    for(count=0xFF; 0!=count; count--)
    {
        scrool(count);
        sleep(1);       /* BDS C にある時間待ちの関数 */
    }
}
コンパイルして TESTFUNC.CRL とリンクさせます。
>cpm cc test\msxvdp.c                        コンパイル

>cpm clink test\msxvdp test\testfunc         msxvdp と TESTFUNC のリンク
MSX で msxvdp.com を実行してみると

にゅろーんと1ドット単位で縦スクロースしました。
やってみるとけっこう簡単に C 言語とマシン語とのリンクができましが、インテルニーモニックだと馴染みが薄いし、表記できない Z80の命令もあるので、ザイログニーモニック編に続きます。

>BDS C の使い方 - 目次