SSブログ
English Version

8080/Z80 リロケータブルコードの実験 [Z80]

 Z80は8080には無かった相対ジャンプ命令が追加されましたが、6809と違い相対コールができません。なのでOS9のようなポジションインディペンデントコード(PIC)なモジュールが書きづらいです。
 昔から議論されていることではありますが、PICは面白いのか?wちょっと考えてみました。

 PICなコール(相対コール)をソフトで実現するためにはプログラムカウンタ(PC)の値を参照する必要があります。
 Z80の命令セット上、コール時のスタックからPCの値を拾えます(それ以外にPCの値を参照する方法はないと思う)

 PCの値さえ参照できれば相対値をコール時のコードに埋め込めば相対コールが実現できます。下記が相対コールのコード例です。'+'が付いている行はマクロ展開で生成された命令です。
Z80 relocatable call
MACRO-80 3.44 09-Dec-81 PAGE 1 ;********************************* ; 8080/Z80 relocatable call test ; 2018/12/24 by skyriver ;********************************* 0028 RELRST equ 028h ; using RST for reloc code ; *** reloc call macro *** rcall macro dest ld de,dest - $ - 4 rst RELRST endm .z80 0000' aseg org RELRST 0028 E1 pop hl 0029 E5 push hl 002A 19 add hl,de 002B E9 jp (hl) org 0100h 0100 test: rcall proc 0100 11 0003 + ld de,proc - $ - 4 0103 EF + rst RELRST 0104 C3 0104 jp $ 0107 00 proc: nop 0108 C9 ret end MACRO-80 3.44 09-Dec-81 PAGE S Macros: RCALL Symbols: 0107 PROC 0028 RELRST 0100 TEST No Fatal error(s)


 机上検討段階でほとんど動作検証ができてしまっているようなものですが実機での確認結果が下記です。ZSIDDはZSIDに小文字シンボル対応と1行ダンプ表示のパッチを適用したものです。
参照)
3チップ構成Pic24CPMマイコン(その4)ZSIDで小文字のシンボルを使う方法その2

 下記のダンプ表示のようにZSIDがRST 38Hを使っているので上のソースから生成したHEXファイルをZSIDではロードできないためSコマンドで手入力しています。

relocatable call code test
a>zsidd ZSID VERS 1.4 #s28 0028 00 e1 0029 00 e5 002A 00 19 002B 00 e9 002C 00 . #s100 0100 01 11 0101 F9 03 0102 21 00 0103 C3 ef 0104 3D c3 0105 01 04 0106 43 01 0107 4F 00 0108 50 c9 0109 59 . #l28 0028 POP HL 0029 PUSH HL 002A ADD HL,DE 002B JP (HL) 002C NOP 002D NOP 002E NOP 002F NOP 0030 NOP 0031 NOP 0032 NOP #l100 0100 LD DE,0003 0103 RST 28H 0104 JP 0104 0107 NOP 0108 RET 0109 LD E,C 010A LD D,D 010B LD C,C 010C LD B,A 010D LD C,B 010E LD D,H #d0 0000: C3 03 FA 00 00 C3 00 CA 00 00 00 00 00 00 00 00 ................ 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0020: 00 00 00 00 00 00 00 00 E1 E5 19 E9 00 00 00 00 ................ 0030: 00 00 00 00 00 00 00 00 C3 86 D8 00 00 00 00 00 ................ 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 20 20 20 ............. 0060: 20 20 20 20 20 20 20 20 00 00 00 50 00 20 20 20 ...P. 0070: 20 20 20 20 20 20 20 20 00 00 00 00 00 FB EA FA ........ 0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ #x ----- A=00 B=0000 D=0000 H=0000 S=0100 P=0100 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 LD DE,0003 #t ----- A=00 B=0000 D=0000 H=0000 S=0100 P=0100 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 LD DE,0003 *0103 #t ----- A=00 B=0000 D=0003 H=0000 S=0100 P=0103 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 RST 28H *0028 #t ----- A=00 B=0000 D=0003 H=0000 S=00FE P=0028 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 POP HL *0029 #t ----- A=00 B=0000 D=0003 H=0104 S=0100 P=0029 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 PUSH HL *002A #t ----- A=00 B=0000 D=0003 H=0104 S=00FE P=002A ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 ADD HL,DE *002B #t ----- A=00 B=0000 D=0003 H=0107 S=00FE P=002B ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 JP (HL) *0107 #t ----- A=00 B=0000 D=0003 H=0107 S=00FE P=0107 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 NOP *0108 #t ----- A=00 B=0000 D=0003 H=0107 S=00FE P=0108 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 RET *0104 #t ----- A=00 B=0000 D=0003 H=0107 S=0100 P=0104 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 JP 0104 *0104 #t ----- A=00 B=0000 D=0003 H=0107 S=0100 P=0104 ----- A'00 B'0000 D'0000 H'0000 X=0000 Y=0000 JP 0104 *0104 #


 想定通り動作することが実機で確認できました(すぐに動かせるCP/Mマシンがあると便利ですね^^)。
 DEとHLレジスタを破壊してしまうし、コール命令が4バイトになってしまいますが、リロケータブルなコールが実現できます(必要な場面があまり思い浮かびませんがw)
 また、上記の例ではRST命令を使っていますが、固定番地へのコール命令でも同様なことが可能です(この場合rcallは6バイト長になるけど)


★追記 2022/12/10
 「8080/Z80 リロケータブルコードの実験(その2)」の記事に DE/HL レジスタ非破壊のリロケータブルコールについて書きました。
 下記の [ 次へ ] からも飛べます。



[TOP] [ 前へ ] 連載記事 [ 次へ ]

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