SSブログ
English Version

メモリ上で実際に動くプログラム(その2) [Z80]

 メモリ上で実際に動き(移動し)通過した後にはNOP命令のみを残してひたすらメモリ上を駆け回る自走プログラムで新たな展開があったので記録しておきたいと思います。
 前回の記事で追記したブロック転送のみによる自走プログラムはアイディアは面白いのですが、前回の記事に書いたように今回の自走プログラムの条件の一つである「一回のコピーでのメモリ上の移動量はなるべく小さくする(数バイト程度)」という点では初版のものより劣っていたのでもっと小刻みに移動するものはできないか考えてみました。

 前回記事に追記したプログラムは PUSH を使わずブロック転送のみで自走プログラムを実現したので逆の発想で PUSH のみで自走プログラムができないかも試みてみます。
 これは結構難しく、できそうではあるけれどもう一歩のところでなかなかできません。
 Z80 はレジスタは多いのですが、PUSH 対象のレジスタペア数は半減しそれほど多くないので 裏レジスタと AF レジスタペアまで利用しました。

 AF レジスタペアを利用するにあたり、フラグレジスタの未使用ビットに値を設定できるのかを検索してみると「Z80のフラグレジスタについて」がヒットしましたが回答は「~~の場合もありうる」という内容で質問に対する回答(できるかできないか)が書いてありません。
 海外のネット情報では例えば「What is the purpose of the reserved/undefined bit in the flag register?」にあるように Z80 のフラグの未使用ビットには値を設定できる旨が書いてありました。

 念のためにザイログ製の Z80 を使って下記のプログラムで確認してみた結果、出力は Ok だったのでフラグの未使用ビットも値を保持できることを確認できました。

POP AF でのフラグの未使用ビットの値の確認(Z80アセンブラ)
;++++++++++++++++++++++++++++++++++++ ; check POP AF flag value ; Ver 0.01 2024/01/25 by skyriver ; Ver 0.02 2024/02/04 by skyriver ;++++++++++++++++++++++++++++++++++++ 0005 BDOS EQU 0005H 0002 COUT EQU 02H ; E<-data 0000' ASEG ORG 0100H 0100 2E 00 START: LD L,0 0102 E5 LOOP: PUSH HL 0103 F1 POP AF 0104 F5 PUSH AF 0105 D1 POP DE 0106 7B LD A,E 0107 BD CP L 0108 20 14 JR NZ,ERR 010A 2C INC L 010B 20 F5 JR NZ,LOOP 010D 21 0123 LD HL,MgOk ; +++ go through +++ 0110 7E Puts: LD A,(HL) 0111 B7 OR A 0112 C8 RET Z 0113 E5 PUSH HL 0114 0E 02 LD C,COUT 0116 5F LD E,A 0117 CD 0005 CALL BDOS 011A E1 POP HL 011B 23 INC HL 011C 18 F2 JR PUTS 011E 21 0126 ERR: LD HL,MgNg 0121 18 ED JR Puts 0123 4F 6B 00 MgOK: "Ok", 0 0126 4E 67 00 MgNg: "Ng", 0 END
※2024/02/04 improved slightly

 今回のプログラムも自身のコードを上書きするのでディバッガでのステップ動作等は使えず、机上ディバッグメインで動かしました。通常のプログラムを組む時の思考とは違う考え方が必要なので結構大変でした。普通に考えると PUSH 対象のレジスタペアが足りないのでレフレックスラジオが一つのトランジスタを高周波と低周波で2回使うように二つのレジスタペアを2回づつ使っています。この共通コードができるようにし、レジスタの使用を節約するように調整するのが難しいパズルでした。

 完成したソースを以下に示します。メモリ上の移動幅は究極の1バイトで、メモリを逆走します。このソースを見て机上で動作を追えるでしょうか? PC と SP がクロスする部分の仕掛け等を堪能してください。

完成した自走プログラム3(Z80アセンブラ)
;+++++++++++++++++++++++++++++++++++++ ; runner code on memory ; Ver 0.03 2024/01/26 by skyriver ;+++++++++++++++++++++++++++++++++++++ 0000' ASEG ORG 0100H 0100 31 0100 START: LD SP,START 0103 21 DB 21H ; LD HL,xxxx 0104 F5 PUSH AF 0105 E5 PUSH HL 0106 E5 PUSH HL 0107 F1 POP AF ; set AF 0108 21 DB 21H ; LD HL,xxxx 0109 D9 EXX 010A C5 PUSH BC 010B 11 DB 11H ; LD DE,xxxx 010C F9 LD SP,HL 010D 2B DEC HL 010E 01 DB 01H ; LD BC,xxxx 010F C5 PUSH BC 0110 D5 PUSH DE 0111 D9 EXX 0112 01 DB 01H ; LD BC,xxxx 0113 F1 DB -(HLVAL - TOP) 0114 00 NOP 0115 11 DB 11H ; LD DE,xxxx 0116 D9 EXX 0117 18 DB 18H ; JR 0118 21 012B LD HL,HLVAL 011B F3 DI 011C F9 TOP: LD SP,HL 011D 2B DEC HL 011E C5 PUSH BC ; NOP : xx 011F D5 PUSH DE ; JR : EXX 0120 D9 EXX 0121 C5 PUSH BC ; PUSH DE : PUSH BC 0122 F5 PUSH AF ; PUSH HL : PUSH AF ; ----------------------- 0123 F5 PUSH AF ; PUSH HL : PUSH AF 0124 E5 PUSH HL ; PUSH BC : EXX 0125 C5 PUSH BC ; PUSH DE : PUSH BC 0126 D5 PUSH DE ; DEC HL : LD SP,HL 0127 D9 EXX 0128 18 FE JR $ 012A 00 NOP 012B HLVAL EQU $ END


★追記 2024/01/28 {
 コード生成に必要な PUSH 回数について考察してみると
  • PUSH 命令(1バイト)で2バイトのメモリを設定できるので PUSH 命令1回につき1バイトのコードを生成できる
  • 今回の自走プログラムでは先頭の LD SP,HL と DEC HL の2バイトと末尾の JR xx と NOP の3バイト及び前進するための伸長分の1バイトの合計6バイトのコード生成が必要となる
  • PUSH 用に使用できるレジスタペアが AF BC DE の3つ(HL レジスタはスタック再設定用に使用)では不足するので更に3つの裏レジスタペアを使用する必要がある
  • 裏レジスタを使用するためには EXX を2回実行する必要があり、必要コードにこの2バイトを加えると8バイトのコード生成(8回の PUSH)が必要となる
以上から8回の PUSH が必要となるのに対して実際に PUSH 可能なレジスタペアは6つ( AF BC DE BC' DE' HL')なので生成コード中に共通部分を作り2回分の PUSH は使用済みのレジスタペアを再利用できるようにする必要があります。
 しかし、生成コードの中には順番を逆転できない制約がある部分があり、今回の自走プログラムはかなり厳しい条件の中で辛うじて達成できたと言えると思います。
}
 前回の記事と同様に自作の Z80 ボードである Z80GalCompact を使って動作確認してみました。
 今回作成した自走プログラムは runcode3 で実行後にリセットし、メモリ上に残っているプログラムのコードを GAME 言語で作成したサーチプログラムで探しています。

Z80GalCompact での自走プログラム3の検証時のログ
Z80GAL Ver 0.01 2020/11/26 by skyriver CP/M loading ... ok 62k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>zsidm ZSIDM Ver 1.4 #f100 cfff e5 #d9000 9000: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9010: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9020: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9030: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9040: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9050: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9060: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9070: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9080: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9090: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 90A0: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ #g0 a>c:runcode3 Z80GAL Ver 0.01 2020/11/26 by skyriver CP/M loading ... ok 62k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>gamec GAME80 for CP/M-80(compiler 0200-1B38) Ver0.05d *READY :\<c:findrun3 8E00-8F36 *READY :0 1' *** find runner code 3 10 A=0 100 @ 110 ;=(A:0)=$F9)*(A:1)=$2B)*(A:2)=$C5) " *** find at $" ??=A #=1000 120 ;=%(A/$1000)=0 / "Searching " ??=A "H" 130 A=A+1 140 @=(A=0) 150 #=-1 1000 B=A/256*256 ;=B<0 B=B-$100 1010 I=0,$10 1020 / ??=B ":" 1030 J=0,15 1032 ;=J=8 " -" 1040 " " ?$=B:J) 1050 @=J+1 1060 B=B+16 1070 @=I+1 *READY :#=1 Searching 0000H Searching 1000H Searching 2000H Searching 3000H Searching 4000H Searching 5000H Searching 6000H Searching 7000H *** find at $7A89 7A00: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A10: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A20: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A30: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A40: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A50: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A60: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A70: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7A80: 00 00 00 00 00 00 00 00 - 00 F9 2B C5 D5 D9 C5 F5 7A90: E5 F5 E5 C5 D5 D9 18 F1 - 00 00 00 00 00 00 00 00 7AA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7AB0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7AC0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7AD0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7AE0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7AF0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 7B00: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 *READY :


 X(旧Twitter)で教えてもらったメモリの全空間が RAM で メモリ上に VRAM をアサインできる MZ-2200 のエミュレータで自走プログラムが VRAM 上を通る時の画面キャプチャを貼っておきます。

EmyuZ-2200 エミュレータでの自走プログラム2表示



★追記 2024/01/27
 EmyuZ-2200 エミュレータのディバッガは RST 命令を使用したソフトウェアディバッガよりも ICE に近いので実行命令直下のメモリを書き換えてもステップ動作が行えたり、スタック直下のメモリを壊したりしません。
 今後ディバッグに活用する場面がありそうで有用なソフトを公開された作者の方に感謝です。
 しかし、上記の自走プログラムで使用しなかったのは奇妙な動きがあったからです。改めて動作を確認してみましたので記録しておきます。

 下記の例では PUSH 命令によって PUSH 命令自身を書き換えています。

PUSH 命令による自己書き換えプログラム
;+++++++++++++++++++++++++++++++++++++ ; runner code on memory ; Ver 0.03 2024/01/26 by skyriver ;+++++++++++++++++++++++++++++++++++++ 0000' ASEG ORG 0 0000 F3 START: DI 0001 31 000A LD SP,SPVAL 0004 AF XOR A 0005 21 DB 21H ; LD HL,xxxx 0006 3C INC A 0007 3C INC A 0008 00 NOP 0009 E5 PUSH HL 000A 00 SPVAL: NOP 000B 00 NOP 000C 00 NOP 000D 00 NOP END


 以下がステップ動作時の画面表示です。「done 00000009 PUSH HL」と表示されずに「done 00000009 INC A」と表示されていますね。Aregはゼロのままでメモリは HL の値に書き換わっているので実際は PUSH HL を実行し、done 表示ではメモリから再読みこみして表示しているようです(つまり実行動作は問題なくて表示が違っているだけ)。極めてレアなケースなので通常の使用には問題ないと思われます。

EmyuZ-2200 のディバッガでのステップ動作結果



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

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

最近遊んだMPU [CH32V]

 最近遊んでみた MPU について書いておきたいと思います。

  1. ルネサス製 RA4M1
     ルネサスさんの Arduino UNO R4 MINIMA を無料で配布し、教育用のビデオで勉強できるという太っ腹企画に応募して最新の UNO R4 を入手出来ました。

    Arduino UNO R4 MINIMA での実験中の様子

     教育用の資料とビデオで Arduino IDE で数個のサンプルプログラムを少しカスタマイズしながら動かしてみました。Arduino は楽でいいですねぇ。
     Arduino IDE は至れり尽くせり感が滲み出てきますがソースを作るより探す面が多くなりがちなことや内部の仕掛けが見えにくい等から個人的にはあまり好きではありません。また RA4M1 は MPU 単体を安価に入手できないのも使用する上で大きなネックになりますね。

    PWM でのLEDジンワリ点滅


  2. WCH製 CH32V
     近年、秋月さんでも取り扱いを始めている安価に入手可能な 32 ビット RISCV MPUです。秋月さんで扱うと電子工作界隈に浸透すると言われますが CH32V はどうでしょうね。私のお気に入りだった PIC24FJ は残念なことにすっかり値段が高くなってしまい使い辛くなってしまいましたが CH32V は円安にも関わらず安価に入手できます。書込みにはWCH-LinkE エミュレータが必要ですが、秋月さんで ¥750 で入手できます。

     最初の設定等は「きょうのかんぱぱ」サイトの「40円RISC-Vマイコン(CH32V003)をArduino IDEでLチカをしてみました」のブログ記事を参考にさせて頂き、すんなり動きました。

    CH32V003J4M6 でのLチカ実験用ハード

     CH32V003J4M6 は安価(¥40)で良いのですが、もっと高機能な CH32V203K8T6(以降CH32V203 と記す)でも遊んでみました。高機能といっても秋月さんで安価(¥120)に入手できます。

     簡単な仕様比較を下表に示します。CH32V203 は SPI 1CH、CAN 1CH、USB 機能等も実装しています。

    clockflashRAMGPIOADCUART/USARTI2CtimerPakage
    CH32V003J4M648MHz16KB2KB6pin6ch1ch1ch4chSOP8
    CH32V203K8T6144MHz64KB20KB26pin10ch2ch1ch6chLQFP32

     CH32V203 は 32 ピンの LQFP パッケージなのでブレッドボードで使えるように DIP 変換基板も購入しました。

    CH32V203 と DIP 変換基板

     ピン間隔が 0.8mm の QFP パッケージなので上下左右の位置合せをしっかるやる必要があり、下図のようにマスキングテープで固定してから半田付けしました。

    CH32V203 の固定

     半田付け後の状態が下の写真になります。うまく半田付けできているみたいですね。

    DIP 変換基板に半田付け後の状態

     Lチカ実験用の回路を下図に示します。ディバッグ用のシリアル受信のために Link-E の Rx も接続しています。

    CH32V203 でのLチカ回路

     ブレッドボードを使って LinkE と LED を接続した状態が下の写真です。右にあるチップは CH32V003J4M6 です。

    CH32V203 でのLチカ実験環境

     Arduino IDE ではすんなりLチカが動きました。

    CH32V203 でのLチカ実験(Arduino IDE)

     次に CH32V の IDE 環境である MounRiver Studio を動かしてみました。
     ”mcuXfamikyのブログ”というブログの「CH32V203(1)資料集め」から始まる一連の記事が大変参考になりました。

     下図が MounRiver Studio でLチカを実行している様子です。ブレークやステップもできるのでこの開発環境は中々いいですね^^

    MounRiver Studio でのLチカ実行画面



★追記 2024/07/15
 「CH32V203で遊ぶ」の記事に MounRiver Studio の開発環境で CH32V203 のソフトウェアを作ってみる内容を記載しました。

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

メモリ上で実際に動くプログラム [Z80]

 下記のX(旧Twitter)に投稿したメッセージではプログラムリストの一部が画面上を動き回ることで実際に「動く」プログラムを実現してみました。



 上記のメッセージにも書いたように学生の頃に自身のコードをメモリの少し先のアドレスにコピーし、コピーしたコードにジャンプすることを繰り返すことでメモリ上で実際に「動く」プログラム(以降、自走プログラムと記す)を書いたことがあります。
 その時使ったマイコンは自作の Z80 を使用したマイコンで起動後は全メモリが RAM になり、メモリ空間の一部を画面表示用の VRAM として使っていました。自走プログラムが VRAM を通過する際、コードに対応したキャラクタが一瞬表示されると共にコード実行時の VRAM のアクセスが CRT コントローラと競合することで画面にノイズが発生することから、VRAM 上を走っているタイミングが画面上で確認できました。

 以前作成した上記の自走プログラムのコード内容を細かくは覚えていないのですが久々にメモリ上を動くプログラムを作ってみることにしました。

 作成するプログラムの条件としては
  • メモリは全て RAM とする
  • 移動後のメモリは 00H にすること(自走プログラムがメモリを一周した後は実行中の自走プログラムに無関係なメモリ領域は全て 00H になるようにする)
  • 一回のコピーでのメモリ上の移動量はなるべく小さくする(数バイト程度)
です。

 中々面白そうなお題目ですね^^

 実際に作ったプログラムの一例を以降に記載しますが、まずは上記のお題目を自分で少し考えてみてから以降を読んだ方がこの記事の内容をより楽しめるかもしれません。



 上記の条件を満たすプログラムを作成するに当たり、最初に考えた方針が下記です。
  1. コードのコピー
     Z80 なのでブロック転送を使用する。コピー対象のソースとディスティネーションのアドレスが変化するので、HL と DE の値は再設定せずに継続して使用するようにする。

  2. コピー後のメモリクリア
     PUSH 命令でコピー元のコードを 00H で上書きする。コピー後は HL がコピー元の最終コードの次のアドレス値になっているのでスタックに HL の値を入れてから必要回数 0000H を PUSH する。

  3. プッシュ用のレジスタ
     ブロック転送で BC,DE,HL のレジスタペアを使用してしまうので 0000H PUSH用のレジスタペアをどうするか・・
    ⇒ ブロック転送後は BC レジスタが零になるのでこれを利用する。

 上記の方針で作成したコードが下記になります。以前作成したものは相対ジャンプを使っていた記憶があるので以前のものより進化したプログラムかもしれません(その分私自身も進化したということかw)。

メモリ上で「動く」プログラムの一例(Z80 アセンブラ)
;+++++++++++++++++++++++++++++++++++++ ; runner code on memory ; Ver 0.01 2024/01/16 by skyriver ; Ver 0.01a 2024/01/30 by skyriver ;+++++++++++++++++++++++++++++++++++++ 0000' ASEG ORG 0100H 0100 21 010B START: LD HL,CSTART 0103 11 0113 LD DE,DST 0106 06 00 LD B,0 0108 3E 08 LD A,CEND - CSTART + 1 010A F3 DI 010B F9 CSTART: LD SP,HL 010C C5 PUSH BC 010D C5 PUSH BC 010E C5 PUSH BC 010F C5 PUSH BC 0110 4F LD C,A ; B=0 0111 ED B0 LDIR 0112 CEND EQU $ - 1 0113 DST EQU $ END
★2023/01/30 若干最適化しました

 前述したメモリの一部を VRAM で使用しているようなマイコン環境は今はないので自作の Z80 ボードである Z80GalCompact を使って動作確認してみました。

 確認手順は下記の通りです。
  1. メモリの設定
     自走プログラムが自コード以外のメモリをゼロクリアしていることを確かめるためにディバッガ(ZSID)を使ってメモリを E5H に設定する。

  2. 自走プログラムの実行
     Cドライブにある自走プログラム(runcode)を実行する。

  3. CP/M の再起動
     CPU をリセットし、CP/M を再起動する。TPA 領域のメモリはリセット時の値が保持されている。

  4. サーチプログラムの実行
     GAME インタープリタを起動し、GAME 言語で記述した自走プログラムのコードサーチプログラムを実行する。

  5. 自走プログラム周辺のメモリ値の確認
     サーチプログラムがメモリ上に残っている自走プログラムのコードを発見し、周辺のメモリも含めたメモリのダンプ表示をするので、メモリがクリアされていることを確認する。下記のログ例では LDIR で3バイトコピー直後にリセットされたようです。周辺のメモリは想定通り零クリアされていますね。


Z80GalCompact での自走プログラムの検証時のログ
Z80GAL Ver 0.01 2020/11/26 by skyriver CP/M loading ... ok 62k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>zsidm ZSIDM Ver 1.4 #f100 cfff e5 #d9000 9000: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9010: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9020: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9030: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9040: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9050: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9060: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9070: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9080: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9090: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 90A0: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ #g0 a>c:runcode Z80GAL Ver 0.01 2020/11/26 by skyriver CP/M loading ... ok 62k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>gamec GAME80 for CP/M-80(compiler 0200-1B38) Ver0.05d *READY :¥<findrun 8E00-8F24 *READY :0 1' *** find runner code 10 A=0 100 @ 110 ;=(A:0)=$F9)*(A:1)=$C5)*(A:2)=$C5) " *** find at $" ??=A #=1000 120 ;=%(A/$1000)=0 / "Searching " ??=A "H" 130 A=A+1 140 @=(A=0) 150 #=-1 1000 B=A/256*256 ;=B<0 B=B-$100 1010 I=0,$10 1020 / ??=B ":" 1030 J=0,15 1040 " " ?$=B:J) 1050 @=J+1 1060 B=B+16 1070 @=I+1 *READY :#=1 Searching 0000H Searching 1000H Searching 2000H Searching 3000H Searching 4000H Searching 5000H *** find at $5BBB 5B00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5BA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5BB0: 00 00 00 00 00 00 00 00 00 00 00 F9 C5 C5 C5 C5 5BC0: 4F ED B0 F9 C5 C5 00 00 00 00 00 00 00 00 00 00 5BD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5BF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 *READY :


 上記のログの最後の部分と同様ですが、自走プログラム実行中にリセットし、メモリ上にある自走プログラムのコードをサーチした際の画面コピーも貼っておきます。このような時にはお手軽に使える GAME 言語が役立ちますね^^

自走プログラムのサーチ結果の画面



★追記 2024/01/18
 メモリを移動しながら通った後のメモリをゼロクリアする自走プログラムで PUSH を使用しない方法を思い付きました。
 ブロック転送で足跡を消すのは難しいと思っていましたが実行中のブロック転送命令をブロック転送命令で上書きすることでブロック転送処理を継続し、ブロック転送により足跡も消してしまう・・という方法です。
 自分自身のコードを上書きするのでステップやブレークが使えず机上ディバッグしたのでディバッグに少し苦労しました。

 ソースを以下に示します(このソースを見て動作を追えるでしょうか?)

メモリ上で「動く」プログラムのもう一つの例(Z80 アセンブラ)
;+++++++++++++++++++++++++++++++++++++ ; runner code on memory ; Ver 0.02 2024/01/18 by skyriver ; Ver 0.02a 2024/01/28 by skyriver ; Ver 0.02b 2024/01/29 by skyriver ;+++++++++++++++++++++++++++++++++++++ 001D BACKAD EQU (NEXT - CSTART + CLDR2 - CLDR1) 0000' ASEG ORG 0100H 0100 21 0103 START: LD HL,CEND - BACKAD 0103 11 010C LD DE,CEND - BACKAD + (CLDR2 - CLDR1) 0106 06 00 LD B,0 0108 3E 1D LD A,BACKAD 010A F3 DI 010B 18 0B JR SETC 010D 00 00 00 00 CSTART: DB 0,0,0,0 0111 00 00 00 00 DB 0,0,0,0 0115 00 DB 0 0116 ED B8 CLDR1: LDDR 0118 4F SETC: LD C,A 0119 09 ADD HL,BC 011A EB EX DE,HL 011B 09 ADD HL,BC 011C EB EX DE,HL 011D 0E 14 LD C,NEXT - CSTART 011F ED B8 CLDR2: LDDR 0120 CEND EQU $ - 1 0121 NEXT EQU $ END
★2023/01/29 若干最適化しました

 前回と同様の確認手順を実行した際のログを以下に示します。今回の自走プログラム名は runcode2 です。メモリ上に残っている自走プログラムの痕跡を見るとブロック転送で次のコードを生成している最中にリセットが掛かったようですね。

Z80GalCompact での自走プログラム2の検証時のログ
Z80GAL Ver 0.01 2020/11/26 by skyriver CP/M loading ... ok 62k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>zsidm ZSIDM Ver 1.4 #f100 cfff e5 #d9000 9000: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9010: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9020: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9030: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9040: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9050: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9060: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9070: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9080: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 9090: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ 90A0: E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 ................ #g0 a>c:runcode2 Z80GAL Ver 0.01 2020/11/26 by skyriver CP/M loading ... ok 62k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>gamec GAME80 for CP/M-80(compiler 0200-1B38) Ver0.05d *READY :¥<c:find2c 8E00-8F34 *READY :0 1' *** find runner code 10 A=0 100 @ 110 ;=(A:0)=$ED)*(A:1)=$B8)*(A:2)=$4F) " *** find at $" ??=A #=1000 120 ;=%(A/$1000)=0 / "Searching " ??=A "H" 130 A=A+1 140 @=(A=0) 150 #=-1 1000 B=A/256*256 ;=B<0 B=B-$100 1010 I=0,$10 1020 / ??=B ":" 1030 J=0,15 1032 ;=J=8 " -" 1040 " " ?$=B:J) 1050 @=J+1 1060 B=B+16 1070 @=I+1 *READY :#=1 Searching 0000H Searching 1000H Searching 2000H Searching 3000H Searching 4000H Searching 5000H Searching 6000H Searching 7000H Searching 8000H Searching 9000H Searching A000H *** find at $A26C A200: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A210: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A220: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A230: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A240: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A250: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A260: 00 00 00 00 00 00 00 00 - 00 00 00 00 ED B8 4F 09 A270: EB 09 EB 0E 14 ED B8 00 - 00 00 00 EB 0E 14 ED B8 A280: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A290: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A2A0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A2B0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A2C0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A2D0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A2E0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A2F0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 A300: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 *READY :


 前回と同様に上記のログの最後の部分と同じ「自走プログラム実行中にリセットし、メモリ上にある自走プログラムのコードをサーチ」した際の画面コピーも貼っておきます。

自走プログラム2のサーチ結果の画面



★追記 2024/01/21
 自走プログラムが走る様子を MZ-2200 のエミュレータの画面により可視化できました。X(旧Twitter)に投稿したメッセージに添付した動画を貼っておきます。




[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー