CP/Mシミュレータで懐かしのインテル8080アセンブラを使う

CP/Mシミュレータ

2017年5月、Altair 8800 simulatorを使用して懐かしいCP/Mを使うことができました。

懐かしいインテル8080アセンブラを書いてみます。

Intel 8080 Diagram

Intel 8080 Diagram

懐かしのインテル8080アセンブラ

初めてマイクロプロセッサi8080のアセンブラを書いたのは、1976年のことです。ベンチャー企業V社でi8080との衝撃の出会いです。

ベンチャー企業V社でインテル8080を使う

趣味でも、TK-80トレーニングキットで休日にプログラミングしていました。命令コード表を参照しながらハンドアセンブルして機械語に変換していました。

TK-80トレーニングキットで趣味のプログラミング

最後に、8bitマイクロプロセッサZ80でプログラミングしたのは1980年代ですので、35年ぶりぐらいにインテル8080のアセンブラを書いたことになります。

当時は、オブジェクトコードを手で直接パッチを当てることをしていましたので、機械語コードを記憶するほど使い込んでいました。しかし、今では命令セットの記憶も曖昧です。命令セット表を見ながらプログラミングしてみると、なんとなく思い出しました。

プログラム仕様

キーボードから入力したキーコードを16進数で表示する。10回繰り返して終了する。

プログラム実行

プログラム実行

CP/Mは、ASCIIコードを採用しています。

  • 数字の’0′ : 16進数で0x30
  • 数字の’1′ : 16進数で0x31
  • アルファベットの’A’ : 16進数で0x41
  • アルファベットの’O’ : 16進数で0x4F
  • アルファベットの’P’ : 16進数で0x50

プログラムコード

キーコードダンプのプログラムを下記に示します。

        title   'KEY CODE DUMP'
;

BDOS    EQU    0005h
;
ASCA    EQU    'A'
ASC0    EQU    '0'
;---------------------------------
        ORG     0100h
START:
        MVI     A,10
        STA     COUNT
LOOP:
        CALL    CONINP    ; CON Input
        PUSH    PSW
        LXI     D,MSGKEY
        CALL    STROUT    ; String Out
        POP     PSW
;
        LXI     H,OUTBUF
        CALL    CV8BIT
;
        LXI     D,OUTBUF
        CALL    STROUT    ; String Out
;
        LDA     COUNT
        DCR     A
        STA     COUNT
        JNZ     LOOP
;
        RET               ; return CP/M
;----------------------------------------
COUNT:  DB      0
;
MSGKEY:
        DB      ' KEY -> $'
OUTBUF:
        DB      'XX',0Dh,0Ah,'$'
;
;========================================
;  Convert A-REG Value(00-FF) to HEX Char
;     (IN)     A  :  00-FF
;     (IN)     HL :  Store Address
;----------------------------------------
CV8BIT:
        MOV     B,A       ; A is CODE
        RRC
        RRC
        RRC
        RRC
        ANI     00Fh      ; A is Up  4bit
        CALL    CV4BIT
        MOV     M,A
        INX     H
        MOV     A,B       ; A is CODE
        ANI     00Fh      ; A is Lo  4bit
        CALL    CV4BIT
        MOV     M,A
        RET
;========================================
;  Convert A-REG Value(0-F) to HEX Char
;     (IN)     A :  Low 4bit 0-F
;     (OUT)    A :  HEX Char
;----------------------------------------
CV4BIT:
        CPI     0Ah
        JM      CNVH10
        ADI     ASCA-ASC0-10
CNVH10:
        ADI     ASC0           ; A is '0'-'9' 'A'-'F'
        RET
;========================================
; CONSOLE INPUT To A-REG
;     (OUT)     A :  Console Input Char
;----------------------------------------
CONINP:
        MVI     C,01H
        CALL    BDOS
        RET
;========================================
; CONSOLE OUTPUT From A-REG
;     (IN)      A :  Console Output Char
;----------------------------------------
CONOUT:
        MVI     C,02H
        MOV     E,A
        CALL    BDOS
        RET
;========================================
; CONSOLE STRING OUTPUT From (DE)
;     (IN)      DE :  String Address
;----------------------------------------
STROUT:
        MVI     C,09H
        CALL    BDOS
        RET
;================================
        END

キーボード入力と画面表示は、CP/M BDOSファンクションコールを使用します。

【プログラム説明】

CP/Mのプログラムは、0100hから開始します。

  • 最初に、繰り返し回数 COUNT ← 10とします。
  • ===LOOP===
  • | コンソール文字入力(CONINP)で、Aレジスタにキーコードを入力します。
  • | コンソールストリング出力(STROUT)で、MSGKEYを表示します。
  • | 8bitヘキサ変換(CV8BIT)で、Aレジスタを16進数文字列に変換してOUTBUFに格納します。
  • | コンソールストリング出力(STROUT)で、OUTBUFを表示します。
  • 繰り返し回数 COUNT をデクリメントして、ゼロになるまで上記を繰り返します。
  • 終了して、CP/Mに制御を戻します。

 

■ 8bitヘキサ変換(CV8BIT) :Aレジスタ[7-0]を16進数文字列変換してHLアドレスから格納

  • AレジスタをBレジスタに待避します。
  • Aレジスタを4回ローテイトして上位4bitと下位4bitを入れ替えます。
  • 0Fhでマスクして、Aレジスタ[7-4]を下位4bitに入れます。
  • 4bitヘキサ変換(CV4BIT)で16進文字列に変換して、アドレスHLに格納してHLをインクリメントします。
  • AレジスタをBレジスタから元に戻します。
  • 0Fhでマスクして、Aレジスタ[3-0]を下位4bitに入れます。
  • 4bitヘキサ変換(CV4BIT)で16進文字列に変換して、アドレスHLに格納します。

 

■ 4bitヘキサ変換(CV4BIT) :Aレジスタ[3-0]を16進数文字列変換

  • 00~09のとき、’0’を足します → (‘0’~’9’)
  • 0A~0Fのとき、(‘A’-‘0’-10) + ‘0’を足します  → (‘A’~’F’)

ASCIIコードの’0’~’9’と’A’~’F’は、連続する文字コードを割り当てていることを利用しています。

プログラムのビルド

CP/Mの8080アセンブラ ASMを使用して、ソースコード KEYCD.ASMをビルドします。拡張子 .ASM は、省略します。

asm KEYCD
CP/M ASM アセンブル

CP/M ASM アセンブル

ディレクトリをみると .PRNと .HEXを生成しました。


拡張子 .PRN のファイルを確認します。

type KEYCD.PRN
N                       title   'KEY CODE DUMP'
                ;
                
 0005 =         BDOS    EQU    0005h
                ;
 0041 =         ASCA    EQU    'A'
 0030 =         ASC0    EQU    '0'
                ;---------------------------------
 0100                   ORG     0100h
                START:
 0100 3E0A              MVI     A,10
 0102 322701            STA     COUNT
                LOOP:
 0105 CD5401            CALL    CONINP    ; CON Input
 0108 F5                PUSH    PSW
 0109 112801            LXI     D,MSGKEY
 010C CD6101            CALL    STROUT    ; String Out
 010F F1                POP     PSW
                ;
 0110 213101            LXI     H,OUTBUF
 0113 CD3601            CALL    CV8BIT
                ;
 0116 113101            LXI     D,OUTBUF
 0119 CD6101            CALL    STROUT    ; String Out
                ;
 011C 3A2701            LDA     COUNT
 011F 3D                DCR     A
 0120 322701            STA     COUNT
 0123 C20501            JNZ     LOOP
                ;
 0126 C9                RET               ; return CP/M
                ;----------------------------------------
 0127 00        COUNT:  DB      0
                ;
                MSGKEY:
 0128 204B455920        DB      ' KEY -> $'
                OUTBUF:
 0131 58580D0A24        DB      'XX',0Dh,0Ah,'$'
                ;
                ;========================================
                ;  Convert A-REG Value(00-FF) to HEX Char
                ;     (IN)     A  :  00-FF
                ;     (IN)     HL :  Store Address
                ;----------------------------------------
                CV8BIT:
 0136 47                MOV     B,A       ; A is CODE
 0137 0F                RRC
 0138 0F                RRC
 0139 0F                RRC
 013A 0F                RRC
 013B E60F              ANI     00Fh      ; A is Up  4bit
 013D CD4A01            CALL    CV4BIT
 0140 77                MOV     M,A
 0141 23                INX     H
 0142 78                MOV     A,B       ; A is CODE
 0143 E60F              ANI     00Fh      ; A is Lo  4bit
 0145 CD4A01            CALL    CV4BIT
 0148 77                MOV     M,A
 0149 C9                RET
                ;========================================
                ;  Convert A-REG Value(0-F) to HEX Char
                ;     (IN)     A :  Low 4bit 0-F
                ;     (OUT)    A :  HEX Char
                ;----------------------------------------
                CV4BIT:
 014A FE0A              CPI     0Ah
 014C FA5101            JM      CNVH10
 014F C607              ADI     ASCA-ASC0-10
                CNVH10:
 0151 C630              ADI     ASC0           ; A is '0'-'9' 'A'-'F'
 0153 C9                RET
                ;========================================
                ; CONSOLE INPUT To A-REG
                ;     (OUT)     A :  Console Input Char
                ;----------------------------------------
                CONINP:
 0154 0E01              MVI     C,01H
 0156 CD0500            CALL    BDOS
 0159 C9                RET
                ;========================================
                ; CONSOLE OUTPUT From A-REG
                ;     (IN)      A :  Console Output Char
                ;----------------------------------------
                CONOUT:
 015A 0E02              MVI     C,02H
 015C 5F                MOV     E,A
 015D CD0500            CALL    BDOS
 0160 C9                RET
                ;========================================
                ; CONSOLE STRING OUTPUT From (DE)
                ;     (IN)      DE :  String Address
                ;----------------------------------------
                STROUT:
 0161 0E09              MVI     C,09H
 0163 CD0500            CALL    BDOS
 0166 C9                RET
                ;================================
 0167                   END

アドレスと機械語とソースコードを並べたリストファイルです。


拡張子 .HEX のファイルを確認します。

type KEYCD.HEX
:100100003E0A322701CD5401F5112801CD6101F1DC
:10011000213101CD3601113101CD61013A27013D77
:10012000322701C20501C900204B4559202D3E2030
:100130002458580D0A24470F0F0F0FE60FCD4A0120
:10014000772378E60FCD4A0177C9FE0AFA5101C636
:1001500007C630C90E01CD0500C90E025FCD0500EE
:07016000C90E09CD0500C91D
:0000000000

機械語がインテルHEXフォーマットで記録されています。


LOADコマンドで、.HEXファイルを実行形式の .COMに変換します。

load KEYCD
CP/M LOADコマンド

CP/M LOADコマンド

 

ディレクトリをみると .COMを生成しました。


KEYCD.COMを実行します。

KEYCD
プログラム実行結果

プログラム実行結果

 

最後に

Altair 8800 simulatorを使用してCP/Mで、久しぶりにインテル8080アセンブラでプログラムを書きました。

大学生から新入社員だったころに、熱中してi8080プログラミングしていたころを思い出しました。

「我が青春の8bitマイコン8080」と、言えるでしょう!