2014年9月16日火曜日

BDS C の使い方 - SHARP X1 で使ってみる


>BDS C の使い方 - 目次

BDS C で マシン語とのリンクのやり方がわかったので、SHARP X1 で I/Oポートを操作してみます。

X1 は I/O空間が16ビットなので、アドレスを16ビットで指定する入出力関数を作りました。
; FILENAME : IO16.CZM
; BDS C 用 16ビットI/O空間入出力
;


        INCLUDE "BDSZASM.LIB"   ; アセンブラから c.ccc (ccc.asm) 
                                ; にアクセスするのに必要なヘッダファイル
        
        
        FUNCTION        in16    ; int in16(address)
        CALL    ma1toh          ; 1つ目の引数を HLとAレジスタに入れる
        PUSH    BC              ; BCレジスタは保存しなければいけない
        LD      B,H
        LD      C,L             ; BC=HL
        IN      A,(C)
        LD      L,A
        LD      H,0
        POP     BC
        RET                     ; HL が返り値になる
        ENDFUNC


        FUNCTION        out16   ; void out16(address, data)
        CALL    ma1toh          ; 1つ目の引数を HLとAレジスタに入れる
        LD      (arg1),HL       ; arg1 はBDSZASM.LIBで定義されているワーク
        CALL    ma2toh          ; 2つ目の引数を HLとAレジスタに入れる
                                ; 同じように 7番目の引数まで取り込める
        PUSH    BC
        LD      BC,(arg1)
        OUT     (C),L
        POP     BC
        RET
        ENDFUNC


        FUNCTION        di      ; 割り込み禁止
        DI
        RET
        ENDFUNC
        
        
        FUNCTION        ei      ; 割り込み許可
        EI
        RET
        ENDFUNC
        
        END

16ビットアドレスの入出力関数を使う簡単なテストで、VRAMの読み書きをするプログラムを作ってみました。
/*
FILENAME : X1.C
SHARP X1 で BDS C を使うテスト

X1 G-RAM はI/O空間
0x2000 - 0x27FF テキストアトリビュート
0x3000 - 0x37FF テキスト
0x4000 - 0x7FFF B
0x8000 - 0xBFFF R
0xC000 - 0xFFFF G
*/

#include <stdio.h>

void main()
{
    short addr;
    
    /* テキストVRAM適当書き込み */
    for(addr=(0x3000+80); (0x3000+80*5)!=addr; addr++)
    {
        out16(addr,addr);
    }
    
    /* テキストVRAM適当読み込みテスト */
    printf("0x3000=%02x\n",in16(0x3000));
    
    /* グラフィックパレット初期化 */
    out16(0x1000,0xAA); /* 1010 1010 */
    out16(0x1100,0xCC); /* 1100 1100 */
    out16(0x1200,0xF0); /* 1111 0000 */
    
    /* プライオリティ */
    /*out16(0x1300,0xFE);*/ /* 1111 1110 */

    /* 同時アクセスモード */
    di();
    out16(0x1A02,0x30); /* 0011 0000 */
    out16(0x1A02,0x10); /* 0001 0000 */
    
    /* GRAMクリア */
    for(addr=0x0000; 0x4000!=addr; addr++)
    {
        out16(addr,0);
    }
    /* 同時アクセス解除 */
    in16(0x1A02);
    ei();
    
    /* GRAM Bプレーン適当書き込み*/
    for(addr=0x4000; 0x8000!=addr; addr++)
    {
        out16(addr,addr);
    }
}

アセンブル、コンパイル、リンクして X1 の CP/M 互換 OS LSX-Dodgers 上で動かします。
>cpm zcasm test\IO16
BDS C CRL-format M80/L80 Preprocessor ver. 1.5
Processing the IN16 function...
Processing the OUT16 function...
Processing the DI function...
Processing the EI function...
C:IO16.MAC is ready to be assembled.

>msdos zasm test\IO16.MAC
/// ZASM /// Z-80 Assembler, MS-DOS version 1.64
Copyright (C) 1988-1994 by K.KAWABATA (Bunbun)

** Pass 1 **  Symbol table size  2000 Symbols
** Pass 2 **

  0 warning(s),   0 error(s) in assembly.

>cpm cload test\IO16
CASM Image Hex-to-Crl Converter -- v1.6
Copyright (c) 1983 William C. Colley III

C:IO16.CRL successfully generated.

>cpm cc test\x1
BD Software C Compiler v1.60  (part I)
  42K elbowroom
BD Software C Compiler v1.60 (part II)
  40K to spare

>cpm clink test\x1 test\io16
BD Software C Linker   v1.60

Last code address: 0F65
Externals start at 0F66, occupy 0006 bytes, last byte at 0F6B
Top of memory: FDFF
Stack space: EE94
Writing output...
  51K link space remaining

>
ちゃんと動きました。

I/O に 1バイト書くのに、引数をスタックにセットして、関数をコールして、関数側で引数を取り出してと効率が悪いので、VRAMのアクセスなどのようにまとまった I/Oアクセスは、マシン語で書くなり DMAを使うなりしないと遅いですね。

>BDS C の使い方 - 目次