SSブログ
English Version

CP/M用hexローダーの製作 [Z80]

 CP/M-80 用のプログラムをアセンブリ言語で書く場合、パソコン上のエディタを使ってソースを編集したいものです。従来は、パソコンで編集したアセンブラソースを Z80 ボードに XMODEM で転送して動かしていました。
 しかし、パソコン上で CP/M エミュレータを使ってアセンブル&リンクして作成した HEX ファイルを TeraTerm 上にドラッグ&ドロップして実行できたらより効率的です。

 そこで CP/M 上で動作する HEX ローダーを作成してみました。このローダーの機能(特徴)は下記の通りです。
  1. コンソールから入力されるインテル HEX 形式のデータをメモリ上に展開します
  2. ロード完了後にHEX ファイルの先頭行のアドレスにジャンプします(ロードプログラムが自動起動します)
  3. CP/M の標準プログラムである 0100H から始まるものもダウンロードできるようにするために自身のコードを 0080H に移動してから実行します
  4. 高速化のために BIOS の機能を直にコールしています

 CP/M 側でこのローダーを起動後に、普通に作成した HEX ファイルを TeraTerm にドラッグ&ドロップすればロード後に自動的に実行されるので転送作業がかなり楽になりました。

 下記のリンクに公開しました。商用利用以外であれば自由に使用可能とします。
[history]
2023/05/15 Ver 0.03 set 00h to 0080H by skyriver
2023/03/26 Ver 0.02 can break by ^C
2023/03/26 Ver 0.01 published


 ソースも貼っておきます。

CP/M-80 用 HEX ローダー(アセンブラ)
;************************************************ ; HexLoader for CP/M ; Ver0.02 2023/03/26 can break by ^C by skyriver ; Ver0.03 2023/05/15 set 00h to 0080H by skyriver ;************************************************ 0001 WBOOTAD EQU 0001H ; wboot address 0080 PROGST EQU 0080H ; bios service No from wboot 0002 CONIN EQU 2 0003 CONOUT EQU 3 ; BDOS service 0005 BDOS EQU 0005H 0009 PrnStr EQU 9 ; print string 0000' ASEG ORG 0100H 0100 3A 0080 HexLd: LD A,(PROGST) 0103 B7 OR A 0104 28 06 JR Z,EXEC 0106 11 0146 LD DE,HlpMsg 0109 C3 00EB JP Puts 010C 21 0170 EXEC: LD HL,CODE_ST 010F 11 0080 LD DE,PROGST 0112 01 007D LD BC,CODE_EN - CODE_ST 0115 ED B0 LDIR 0117 2A 0001 LD HL,(WBOOTAD) 011A EB EX DE,HL 011B 21 0007 LD HL,3 * CONIN + 1 011E 19 ADD HL,DE 011F 4E LD C,(HL) 0120 23 INC HL 0121 46 LD B,(HL) 0122 ED 43 00F1 LD (CONINA),BC 0126 21 000A LD HL,3 * CONOUT + 1 0129 19 ADD HL,DE 012A 4E LD C,(HL) 012B 23 INC HL 012C 46 LD B,(HL) 012D ED 43 00F5 LD (CONOUTA),BC 0131 C3 0080 JP PROGST 0134 48 65 78 4C HexMsg: DB 'HexLoader Start',13,10,'$' 0138 6F 61 64 65 013C 72 20 53 74 0140 61 72 74 0D 0144 0A 24 0146 48 45 58 4C HlpMsg: DB 'HEXLOAD Ver 0.03 2023/05/15 by skyriver',13,10,'$' 014A 4F 41 44 20 014E 56 65 72 20 0152 30 2E 30 33 0156 20 32 30 32 015A 33 2F 30 35 015E 2F 31 35 20 0162 62 79 20 73 0166 6B 79 72 69 016A 76 65 72 0D 016E 0A 24 0170 CODE_ST EQU $ .phase PROGST 0080 00 NOP ; command parameter length 0081 11 0134 LD DE,HexMsg 0084 CD 00EB CALL Puts 0087 16 00 LD D,0 ; first flag 0089 CD 00F0 LOAD: CALL GETCH 008C FE 03 CP 'C' - 40H 008E CA 0000 JP Z,0 0091 FE 3A CP ':' 0093 20 F4 JR NZ,LOAD 0095 CD 00D5 CALL RDBYTE ; get byte count 0098 47 LD B,A 0099 CD 00E2 CALL RDWORD ; get address 009C 7A LD A,D 009D B7 OR A 009E 20 03 JR NZ,RDTYPE 00A0 16 01 LD D,1 ; clear flag 00A2 E5 PUSH HL ; set execute address 00A3 CD 00D5 RDTYPE: CALL RDBYTE ; get record type 00A6 5F LD E,A ; save type 00A7 FE 01 CP 1 00A9 28 14 JR Z,DSPTYP ; end of data 00AB B7 OR A 00AC 20 0C JR NZ,LdErr ; data record 00AE CD 00D5 RDDATA: CALL RDBYTE 00B1 77 LD (HL),A 00B2 23 INC HL 00B3 10 F9 DJNZ RDDATA 00B5 CD 00BF CALL DSPTYP 00B8 18 CF JR LOAD 00BA 21 00F7 LdErr: LD HL,ErrMsg ; error occur 00BD 18 2C JR Puts 00BF CD 00D5 DSPTYP: CALL RDBYTE ; read check sum 00C2 CD 00F0 CALL GETCH ; read delimitor 00C5 7B LD A,E ; get type 00C6 C6 30 ADD A,'0' 00C8 18 29 JR PUTCH ; read hex nible ; A -> data 00CA CD 00F0 RDNBL: CALL GETCH 00CD D6 30 SUB '0' 00CF FE 0A CP 10 00D1 D8 RET C 00D2 C6 F9 ADD A,10 + '0' - 'A' 00D4 C9 RET ; read byte data ; A -> byte data 00D5 CD 00CA RDBYTE: CALL RDNBL 00D8 07 RLCA 00D9 07 RLCA 00DA 07 RLCA 00DB 07 RLCA 00DC 4F LD C,A 00DD CD 00CA CALL RDNBL 00E0 B1 OR C 00E1 C9 RET ; read hex word ; HL -> data 00E2 CD 00D5 RDWORD: CALL RDBYTE 00E5 67 LD H,A 00E6 CD 00D5 CALL RDBYTE 00E9 6F LD L,A 00EA C9 RET ; display message ; DE <- message address 00EB 0E 09 Puts: LD C,PrnStr 00ED C3 0005 JP BDOS 00F0 C3 GETCH: DB 0C3H 00F1 0000 CONINA: DW 0 00F3 4F PUTCH: LD C,A 00F4 C3 DB 0C3H 00F5 CONOUTA: 00F5 0000 DW 0 00F7 65 72 72 0D ErrMsg: DB 'err',13,10,0 00FB 0A 00 .dephase 01ED CODE_EN EQU $ END Macros: Symbols: 0005 BDOS 01ED CODE_EN 0170 CODE_ST 0002 CONIN 00F1 CONINA 0003 CONOUT 00F5 CONOUTA 00BF DSPTYP 00F7 ERRMSG 010C EXEC 00F0 GETCH 0100 HEXLD 0134 HEXMSG 0146 HLPMSG 00BA LDERR 0089 LOAD 0009 PRNSTR 0080 PROGST 00F3 PUTCH 00EB PUTS 00D5 RDBYTE 00AE RDDATA 00CA RDNBL 00A3 RDTYPE 00E2 RDWORD 0001 WBOOTAD No Fatal error(s)


nice!(0)  コメント(3) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 3

neko Java

CP/Mの機能だけでやろうとすると、

PIP HOGE.HEX=CON:
^Z
DDT HOGE.HEX

バイナリの保存はSAVEで可能だけど256バイト単位でしかできないです。
by neko Java (2023-03-26 02:45) 

skyriver

 このローダーはあくまでもCP/M上で実行するのが目的でファイルとして保存することを目的にしていません。
 実機でロジアナ等で動作をモニタしながらソース変更してハード&ソフトディバッグする際等に有効と思います。
by skyriver (2023-03-26 03:02) 

neko Java

なるほど。ファイル化の手間が省けるのですね。

私は、DDTはHEXを指定するとBIN化してメモリにロードされるので、そこからGコマンドで実行してます。

あと、LOADでHEXはCOMにできるのを忘れてました。
by neko Java (2023-03-26 03:56) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。