Pic24MC68Kマイコン(その11)CP/M-68KでForth [68K]
「Pic24MC68Kマイコン(その9)ehBASICの移植」の記事で書いたように MC68000 のチップサイズと同程度のサイズのプリント基板でCP/M-68Kが動き、ehBASIC も移植できたので CP/M-68K で動作する BASIC 以外のアプリケーションを探していたところ、Digital Reseaerch Binary Files のサイトに Forth があったことを思い出し、起動しようと試みましたが下記のエラーが発生して動きませんでした。orz
実行ファイルの先頭部分をダンプしてみるとリロケーションビットは立っておらず(=リロケータブルでは無い)テキストセグメントの開始アドレスが 0x0500 になっています(ファイルヘッダの構造は下図を参照してください)
今回開発した自作ボードでは CP/M 本体を 0x0400 からに配置しているので 0x0500 にアプリケーションを置くことはできません。
Forth83 にはソースが同梱されていなかったので他の Forth は無いか探したところ、CP/M-68K 用ではありませんが 68K 用の Fig-FORTH がソース付きで見つかりました。アセンブラソースのコンソール入出力部分を下記のように CP/M-68K 用に書き換え、また CP/M-68K のアセンブラ(as68)が通るように変更しました。
DDT を使って動作確認したところ、下図のように A0 レジスタ設定箇所が ワード指定のため符号拡張されてしまいアクセス違反が発生する状況でした。下記の例では A0 を修正してステップ動作を続行していますが、更にその先で A6 が符号拡張されてしまっています。
Fig-FORTHのソースではデータのポインタを全てワード(2バイト)で扱っているのでデータエリアが 0x8000 以降にあるとアドレス設定時に符号拡張されてしまいうまく動きません(MC68Kはメモリ空間が 16MB あるのに先頭の 32KB の範囲でしか動かせない)。orz
また、コールドスタート時に下記のように $2F00 番地(何故ラベルでは無くイミーディエット値のアドレスなのか?)のメモリに書込みを行っているので CP/M を壊してしまいます。
結果としては Fig-FORTH と最初に書いた Forth83 が動かない原因は、今回開発したボードで CP/M 本体をメモリの先頭に配置したことが大きな原因であるいうことになってしまいました。ネットで入手できる CP/M-68K のアーカイブファイルに CP/M を 0400H に配置したサンプル(CPM400.SR)があり、CP/M の配置場所が実装メモリサイズに依存しない点が気に入り採用したのですが問題が発生する事例に出会ったので、CP/M 本体をメモリの後方に配置することで対応します。
「3チップ構成Pic24CPM68Kマイコン(CP/M-68K起動までの作業まとめ)」の記事で公開している Pic24CPM68K ボード用の CP/M インストール用ファイルも メモリ上位に CP/M を配置するように修正しておきました。
CP/M の Programmer's Guid にもメモリモデルについては下記のように書いてありました。
しかし、CP/M-68K には reloc コマンドが用意されていることや BIOS 内の memory region データで使用可能なメモリの先頭アドレスとサイズを複数設定できる仕様になっていることを考えると TPA が 0x0400 から始まる前提のアプリケーション側にも少し問題があると思います(今回の Fig-FORTH は CP/M 用ではないので当てはまりませんが)
CP/M-68K のメモリ位置の変更は BIOS の memory region 部の値を変えるだけなので直ぐに対応できます(CP/M-68Kはbiosの変更時には A: ドライブのCPM.SYSを差換えるだけなので楽です)
冒頭に書いた Forth83 は1983年に制定された規格で Forth の中では新しいみたいなので気を取り直してこれを動かしてみました。
CP/M-68K 本体をメモリの後方に移動し 0x0400 から TPA として使えるようになったので想定通り Forth83 が動作するようになりました。
ダウンロードしたアーカイブファイルには F83.68K が含まれていたので再構築する必要はないのですが、登録 word をカスタマイズする場合等のために README.TXT に書いてあった再構築手順を書いておきます。
[セルフコンパイルの手順]
日本語のマニュアルがあるといいのですが見つからなかったので F83 TUTOR を参考にしました(まだ読んでいる途中ですが)
動作確認のために hello 表示と階乗ではなく階和?のワードを作成した際のログを貼っておきます。
実は階和の方はWeb上のサービスである Try It Online の gForth 環境で適当に作ったものが動いたので Froth83 でも試して見たものです(まだ慣れていないので冗長な処理になっているかも)。こういう手軽な環境があると今更と言う感じもするのですが、やはり実際のボード上で CP/M-68K を使って動かすと格別な楽しさを感じますね ^^
★追記 2022/02/25 {
Forth のソースファイルである BLK ファイルの作成と編集及び実行ファイルの作成方法について操作方法を確認しましたので操作サンプルを貼っておきます。
}
★追記 2022/02/25 {
Forth でリカーシブコールするためには WORD 定義中に WORD 自身の名前を書くのではなく、RECURSE という WORD を書くことで実現できます。上記で書いた階和をリカーシブコールで再定義したものを以下に示します。少し見易くなりましたね。
同様のロジックで加算を乗算に変えれば階乗の WORD も定義できます。
フィボナッチ数列も再帰呼出しで簡単に書けました。
}
★変更 2022/02/26
再帰呼出しワードの定義はワード名直後に RECURSIVE と書けば定義内で自分自身を名前でコールできるのようなので上記のフィボナッチの定義では RECURSIVE を使うように変更しました。RECURSE という書き方は元々は定義部分のワード名を変更した場合に書き換える箇所を少なくするためのようですが、個人的には自身の名前を使って定義した方がしっくり来て見易いように感じます。
★追記 2022/03/06
Forthでの変数宣言は ”variable 変数名” で可能ですが、配列の使い方について確かめてみました。
create と allot のワードにより配列名に対して領域を確保し、"!" で配列要素に値を設定、"@" で配列要素の値をスタック上に置くことが出来ます。領域確保時のサイズの値はバイト単位で指定し、ディフォルトの整数サイズが2バイトなのでサイズは「要素数x2」の値で設定する必要があります。gForth 等では cells のワードで1ワードのバイト数を掛けることで領域を要素数で指定できるようですが F83 は対応していないようです。
配列宣言、要素への値の設定と読み出しのサンプルを貼っておきます。
[TOP] [ 前へ ] 連載記事 [ 次へ ]
Forth83 起動時のエラー |
---|
P>f83 Insufficient memory or bad file header P>a:dump f83.68k 0000 00 (000000): 601A 0000 70C4 0000 0000 0000 0000 0000 *`...pD..........* 0000 10 (000010): 0000 0000 0000 0000 0500 FFFF 4EF8 32D2 *............Nx2R* 0000 20 (000020): 4EF8 32C6 3E1D 2847 3E1C 2047 4ED0 1003 *Nx2F>.(G>. GNP..* 0000 30 (000030): 0000 8546 4F52 54C8 301E 7044 70BA 701E *...FORTH0.pDp:p.* 0000 40 (000040): 6FCC 0000 3D0D 2A4C 4EF8 0508 1004 0000 *oL..=.*LNx......* 0000 50 (000050): 8445 5849 54A0 053C 3E1E 2A47 4EF8 0508 *.EXIT .<>.*GNx..* 0000 60 (000060): 1004 0532 8655 4E4E 4553 54A0 053C 3D0D *...2.UNNEST .<=.* 0000 70 (000070): 2A5F 3F0C 4EF8 0508 1005 0546 8255 50A0 **_?.Nx.....F.UP * 0001 00 (000080): 0556 32EC 3F14 4EF8 0508 3014 D078 0566 *.V2l?.Nx..0.Px.f* 0001 10 (000090): 3F00 4EF8 0508 1005 0000 8528 4C49 54A9 *?.Nx.......(LIT)* 0001 20 (0000A0): 0586 3F1D 4EF8 0508 1009 0514 8642 5241 *..?.Nx.......BRA* 0001 30 (0000B0): 4E43 48A0 059A 3E15 2A47 4EF8 0508 1009 *NCH ..>.*GNx....* 0001 40 (0000C0): 0000 873F 4252 414E 43C8 05B0 4A5F 67E6 *...?BRA P> |
実行ファイルの先頭部分をダンプしてみるとリロケーションビットは立っておらず(=リロケータブルでは無い)テキストセグメントの開始アドレスが 0x0500 になっています(ファイルヘッダの構造は下図を参照してください)
今回開発した自作ボードでは CP/M 本体を 0x0400 からに配置しているので 0x0500 にアプリケーションを置くことはできません。
CP/M-68K の実行ファイルのヘッダ構造 |
|
Forth83 にはソースが同梱されていなかったので他の Forth は無いか探したところ、CP/M-68K 用ではありませんが 68K 用の Fig-FORTH がソース付きで見つかりました。アセンブラソースのコンソール入出力部分を下記のように CP/M-68K 用に書き換え、また CP/M-68K のアセンブラ(as68)が通るように変更しました。
Fig-FORTH のコンソール入出力部分のCP/M対応へ変更 |
---|
233 BDOS EQU 2 234 235 * putc 236 * D0.B <- data 237 * 238 00000004 48E7C000 XEMIT MOVEM.L D0-D1,-(SP) * save D0,D1 239 00000008 2200 MOVE.L D0,D1 240 0000000A 7002 MOVEQ #2,D0 241 0000000C 4E42 TRAP #BDOS 242 0000000E 4CDF0003 MOVEM.L (SP)+,D0-D1 243 00000012 4E75 RTS 244 * getc 245 * D0.W -> data 246 00000014 2F01 XKEY MOVE.L D1,-(SP) * save D1 247 00000016 303C0006 MOVE.W #6,D0 248 0000001A 323C00FF MOVE.W #$FF,D1 249 0000001E 4E42 TRAP #BDOS 250 00000020 221F MOVE.L (SP)+,D1 251 00000022 4E75 RTS 252 * 253 00000024 700D XCR MOVEQ #ACR,D0 254 00000026 61DC BSR XEMIT 255 00000028 700A MOVEQ #LF,D0 256 0000002A 61D8 BSR XEMIT 257 0000002C 4E75 RTS 258 * 259 * kbhit 260 * D0.W -> 0:none 261 0000002E 2F01 XQTERM MOVE.L D1,-(SP) * save D1 262 00000030 303C0006 MOVE.W #6,D0 263 00000034 323C00FE MOVE.W #$FE,D1 264 00000038 4E42 TRAP #BDOS 265 0000003A 221F MOVE.L (SP)+,D1 266 0000003C 4E75 RTS 267 * 268 0000003E 4E75 XRSLW RTS 269 * |
DDT を使って動作確認したところ、下図のように A0 レジスタ設定箇所が ワード指定のため符号拡張されてしまいアクセス違反が発生する状況でした。下記の例では A0 を修正してステップ動作を続行していますが、更にその先で A6 が符号拡張されてしまっています。
DDT で Fig-FORTH の動作確認 |
---|
P>a:ddt f68k.rel ******************************************************** * DDT-68K 9/20/84 Version 1.3 * * Serial #XXXX-0000 All Rights Reserved * * Copyright 1982,1983,1984,1985 Digital Research Inc. * ******************************************************** File is relocatable text base = 00007000 data base = 00008758 bss base = 00008758 text length = 00001758 data length = 00000000 bss length = 00000002 base page address = 00006F00 initial stack pointer = 000F55DE -t PC=00008696 USP=000F55D6 SSP=0000626C ST=0000=>IM=0 D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 A 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000F55D6 movea.w #$86E2,A0 .COLDUS -l 00008696 movea.w #$86E2,A0 .COLDUS 0000869A move.w (A0),$2F00 000086A0 movea.w $4(A0),A6 000086A4 movea.w A6,A1 000086A6 move.w #$A,D0 COLD1: 000086AA move.w (A0)+,(A1)+ 000086AC dbf D0,86AA .COLD1 000086B0 adda.w #$1E,A1 000086B4 move.w #$D,D0 COLD2: 000086B8 move.w (A0)+,(A1)+ -t PC=0000869A USP=000F55D6 SSP=0000626C ST=0000=>IM=0 D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 A FFFF86E2 00000000 00000000 00000000 00000000 00000000 00000000 000F55D6 move.w (A0),$2F00 -xa0 A0=FFFF86E2 86e2 -t PC=000086A0 USP=000F55D6 SSP=0000626C ST=0008=>IM=0 NEG D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 A 000086E2 00000000 00000000 00000000 00000000 00000000 00000000 000F55D6 movea.w $4(A0),A6 -t PC=000086A4 USP=000F55D6 SSP=0000626C ST=0008=>IM=0 NEG D 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 A 000086E2 00000000 00000000 00000000 00000000 00000000 FFFF9158 000F55D6 movea.w A6,A1 - |
Fig-FORTHのソースではデータのポインタを全てワード(2バイト)で扱っているのでデータエリアが 0x8000 以降にあるとアドレス設定時に符号拡張されてしまいうまく動きません(MC68Kはメモリ空間が 16MB あるのに先頭の 32KB の範囲でしか動かせない)。orz
また、コールドスタート時に下記のように $2F00 番地(何故ラベルでは無くイミーディエット値のアドレスなのか?)のメモリに書込みを行っているので CP/M を壊してしまいます。
Fig-FORTH のコールドスタート処理部分 |
---|
3292 00001694 1696 COLD DC.W 2+* 3293 00001696 307C16E2 MOVE.W #COLDUS,A0 * BOOTLIST 3294 0000169A 33D000002F00 MOVE.W (A0),$2F00 * TOP NFA 3295 000016A0 3C680004 MOVE.W 4(A0),A6 * SET USER POINTE 3296 000016A4 324E MOVE.W A6,A1 * WORK COPY OF US 3297 000016A6 303C000A MOVE.W #$0A,D0 * MOVE ELEVEN BOO 3298 000016AA 32D8 COLD1 MOVE.W (A0)+,(A1)+ * ONE AT A TIME 3299 000016AC 51C8FFFC DBF D0,COLD1 * UNTIL DONE, 3300 000016B0 D2FC001E ADD.W #$1E,A1 * POINT TO BYTE U 3301 000016B4 303C000D MOVE.W #$0D,D0 * MOVE 14 MORE BO |
結果としては Fig-FORTH と最初に書いた Forth83 が動かない原因は、今回開発したボードで CP/M 本体をメモリの先頭に配置したことが大きな原因であるいうことになってしまいました。ネットで入手できる CP/M-68K のアーカイブファイルに CP/M を 0400H に配置したサンプル(CPM400.SR)があり、CP/M の配置場所が実装メモリサイズに依存しない点が気に入り採用したのですが問題が発生する事例に出会ったので、CP/M 本体をメモリの後方に配置することで対応します。
「3チップ構成Pic24CPM68Kマイコン(CP/M-68K起動までの作業まとめ)」の記事で公開している Pic24CPM68K ボード用の CP/M インストール用ファイルも メモリ上位に CP/M を配置するように修正しておきました。
CP/M の Programmer's Guid にもメモリモデルについては下記のように書いてありました。
CP/M-69K Default Memory Model |
|
しかし、CP/M-68K には reloc コマンドが用意されていることや BIOS 内の memory region データで使用可能なメモリの先頭アドレスとサイズを複数設定できる仕様になっていることを考えると TPA が 0x0400 から始まる前提のアプリケーション側にも少し問題があると思います(今回の Fig-FORTH は CP/M 用ではないので当てはまりませんが)
CP/M-68K のメモリ位置の変更は BIOS の memory region 部の値を変えるだけなので直ぐに対応できます(CP/M-68Kはbiosの変更時には A: ドライブのCPM.SYSを差換えるだけなので楽です)
冒頭に書いた Forth83 は1983年に制定された規格で Forth の中では新しいみたいなので気を取り直してこれを動かしてみました。
CP/M-68K 本体をメモリの後方に移動し 0x0400 から TPA として使えるようになったので想定通り Forth83 が動作するようになりました。
ダウンロードしたアーカイブファイルには F83.68K が含まれていたので再構築する必要はないのですが、登録 word をカスタマイズする場合等のために README.TXT に書いてあった再構築手順を書いておきます。
[セルフコンパイルの手順]
- KERNEL.68K の作成
A: ドライブに F83.38K、B: ドライブに META68.BLK と KERNEL68.BLK を配置し、B:ドライブ上で次のコマンドを実行する。B>a:f83 meta68.blk 1 load bye B>
すると A: ドライブに KERNEL.68K が作成されます。
- F83.68K の作成
A: ドライブに EXTEND68.BLK と CPU68000BLK を配置し次のコマンドを実行する。A>kernel extend68 1 load bye A>
すると F83.68K が作成されます。
日本語のマニュアルがあるといいのですが見つからなかったので F83 TUTOR を参考にしました(まだ読んでいる途中ですが)
動作確認のために hello 表示と階乗ではなく階和?のワードを作成した際のログを貼っておきます。
Forth83 での Hello表示例 |
---|
P>f83 68000 Forth 83 Model Version 2.1.0 Modified 03Jun84 : hel begin crlf ." Hello,world" 1- dup 0= until drop ; ok 3 hel Hello,world Hello,world Hello,world ok .s Empty ok : sum dup begin 1- dup rot + swap dup 1 = until drop . ; ok 10 sum 55 ok bye 114 Pages P> |
実は階和の方はWeb上のサービスである Try It Online の gForth 環境で適当に作ったものが動いたので Froth83 でも試して見たものです(まだ慣れていないので冗長な処理になっているかも)。こういう手軽な環境があると今更と言う感じもするのですが、やはり実際のボード上で CP/M-68K を使って動かすと格別な楽しさを感じますね ^^
★追記 2022/02/25 {
Forth のソースファイルである BLK ファイルの作成と編集及び実行ファイルの作成方法について操作方法を確認しましたので操作サンプルを貼っておきます。
blkファイルと実行ファイル作成の操作例 |
---|
P>f83 68000 Forth 83 Model Version 2.1.0 Modified 03Jun84 10 create-file my.blk ok 0 edit Enter your ID: test blk .. Scr # 0 MY.BLK 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 0 ^ ok 0 ^ p \ test how to create block and execute file ok 0 ^\ test how to create block and execute file done 0 modified ok 1 edit Scr # 1 MY.BLK 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 0 ^ ok 0 ^ p \ test block ok 0 ^\ test block u : hel cr ." Hello, world" 0 0 bdos ; ok 1 ^: hel cr ." Hello, world" 0 0 bdos ; done 1 modified ok update ok see hel HEL ? 1 load ok see hel : HEL CR (.") Hello, world 0 0 BDOS ; ok ' hel is boot ok save-system hello.68k ok hel Hello, world P>a:stat hello.68k DRIVE P: USER : 0 RECS BYTES FCBS ATTRIBUTES NAME 227 30K 2 DIR RW P:HELLO .68K ---------------------------------------------- TOTAL: 30K 2 P: RW, FREE SPACE: 618K P>hello Hello, world P> |
}
★追記 2022/02/25 {
Forth でリカーシブコールするためには WORD 定義中に WORD 自身の名前を書くのではなく、RECURSE という WORD を書くことで実現できます。上記で書いた階和をリカーシブコールで再定義したものを以下に示します。少し見易くなりましたね。
同様のロジックで加算を乗算に変えれば階乗の WORD も定義できます。
フィボナッチ数列も再帰呼出しで簡単に書けました。
Forth でのリカーシブコール例 |
---|
P>f83 68000 Forth 83 Model Version 2.1.0 Modified 03Jun84 : sum ( n -- sum ) dup 1 > if dup 1- RECURSE + then ; ok 10 sum . 55 ok ok : fact ( n -- fact ) dup 1 > if dup 1- RECURSE * then ; ok 10 fact . 24320 ok : fibo ( n -- fibo ) RECURSIVE dup 1 > if 1- dup fibo swap 1- fibo + then ; ok : fibo10 11 0 do cr i dup ." fibo( " . ." ) = " fibo . loop ; ok fibo10 fibo( 0 ) = 0 fibo( 1 ) = 1 fibo( 2 ) = 1 fibo( 3 ) = 2 fibo( 4 ) = 3 fibo( 5 ) = 5 fibo( 6 ) = 8 fibo( 7 ) = 13 fibo( 8 ) = 21 fibo( 9 ) = 34 fibo( 10 ) = 55 ok |
}
★変更 2022/02/26
再帰呼出しワードの定義はワード名直後に RECURSIVE と書けば定義内で自分自身を名前でコールできるのようなので上記のフィボナッチの定義では RECURSIVE を使うように変更しました。RECURSE という書き方は元々は定義部分のワード名を変更した場合に書き換える箇所を少なくするためのようですが、個人的には自身の名前を使って定義した方がしっくり来て見易いように感じます。
★追記 2022/03/06
Forthでの変数宣言は ”variable 変数名” で可能ですが、配列の使い方について確かめてみました。
create と allot のワードにより配列名に対して領域を確保し、"!" で配列要素に値を設定、"@" で配列要素の値をスタック上に置くことが出来ます。領域確保時のサイズの値はバイト単位で指定し、ディフォルトの整数サイズが2バイトなのでサイズは「要素数x2」の値で設定する必要があります。gForth 等では cells のワードで1ワードのバイト数を掛けることで領域を要素数で指定できるようですが F83 は対応していないようです。
配列宣言、要素への値の設定と読み出しのサンプルを貼っておきます。
Forth83 での配列宣言と値の設定及び読み出し操作のサンプル |
---|
P>f83 68000 Forth 83 Model Version 2.1.0 Modified 03Jun84 hex ok create abc 8 allot ok : setar ( -- ) 4 0 do i dup 2 * abc + ! loop ; ok : dspar ( -- ) 4 0 do i 2 * abc + @ . loop ; ok setar ok dspar 0 1 2 3 ok abc 10 dump 0 1 2 3 4 5 6 7 8 9 A B C D \/ F 0123456789ABCDVF 70C0 54 D9 70 AC 00 00 70 BA 83 41 42 C3 05 56 00 00 TYp,..p:.ABC.V.. 70D0 00 01 00 02 00 03 00 00 6F CC 85 53 45 54 41 D2 ........oL.SETAR ok abc . 70CE ok |
[TOP] [ 前へ ] 連載記事 [ 次へ ]
Pic24MC68Kマイコン(その10)CP/Mアセンブラの謎 [68K]
前回の「Pic24MC68Kマイコン(その9)ehBASICの移植」の記事で書いたように CP/M-68 のアセンブラ(as68)でソース内で offset セクションで宣言したシンボルがあるとリンカー(lo68 及び link68 共に)でオブジェクトファイル読込み時にエラーが発生してリンクが出来ません。
「CP/M-68K Programmer's Guide」にはoffset については下図のように「(offset宣言で作成した)ストレージ定義はリンカーに渡されません」と言うようなことが書いてあります。
下図はエラー(File Format error: Invalid symbol flags = 100100)発生の再現実験した時の画面キャプチャーです。
マニュアルには説明があるのに実際には使えないというのは実に気になりますね。
下図は上のソースをアセンブルして生成された test.o のダンプ画面のキャプチャです。
赤丸で囲った部分が offset 属性のシンボルのタイプデータになります。ファイルヘッダの構造は Programmer's Guide に書かれている実行ファイルのものと同様で、シンボルデータの構造は
再度、「CP/M-68K Programmer's Guide」を確認したところ、シンボルタイプについての記述がありました。
やはり、offset シンボルタイプの値の 8040H に該当するものはありませんね。
しかし、ここまで解れば、object ファイル内の offset 属性シンボルを equ 属性シンボルに変更すればリンクできそうであるということが推測できます。
試しに 上記の変換機能を有するシンボル変換ツール(convsym)を作って、冒頭で図を貼った test.s のオブジェクトファイルを変換してリンク&実行してみた結果が下記になります。想定外の TRAP が発生することもなく、正常に終了しています。
前回の「Pic24MC68Kマイコン(その9)ehBASICの移植」の記事では offset 属性のシンボルがあるとリンクエラーが発生するので ソース内の offset シンボルを全て equ 宣言に書き換えて対応しましたが、元の offset 宣言のソースから作成したオブジェクトファイルを今回作成した convsym ツールで変換後にリンクすることで ehBASIC も問題無く動作しました。^^
equ 宣言ではソースのメンテ性が悪くなるので、ehBASIC のアセンブラソースも offset 宣言に戻しました。
変換時の画面キャプチャが下図になります。変換された offset 属性のシンボル名が値と共に表示されます。
使用する人は居ないとは思いますが今回作成したシンボル変換ツールも前回記事の末尾で公開しました。
[TOP] [ 前へ ] 連載記事 [ 次へ ]
「CP/M-68K Programmer's Guide」にはoffset については下図のように「(offset宣言で作成した)ストレージ定義はリンカーに渡されません」と言うようなことが書いてあります。
Programmer's Guidでのoffsetに関する記述 |
|
下図はエラー(File Format error: Invalid symbol flags = 100100)発生の再現実験した時の画面キャプチャーです。
offset 属性シンボルのリンク時のエラー |
|
マニュアルには説明があるのに実際には使えないというのは実に気になりますね。
下図は上のソースをアセンブルして生成された test.o のダンプ画面のキャプチャです。
test.o のダンプ |
|
赤丸で囲った部分が offset 属性のシンボルのタイプデータになります。ファイルヘッダの構造は Programmer's Guide に書かれている実行ファイルのものと同様で、シンボルデータの構造は
char name[8]; WORD type; LONG value;のようになっているようです。また、上のダンプからタイプの値は
equ : C000H data : 8400H text : 8200H bss : 8100H offset: 8040Hであることが判ります。
再度、「CP/M-68K Programmer's Guide」を確認したところ、シンボルタイプについての記述がありました。
シンボルタイプ |
|
やはり、offset シンボルタイプの値の 8040H に該当するものはありませんね。
しかし、ここまで解れば、object ファイル内の offset 属性シンボルを equ 属性シンボルに変更すればリンクできそうであるということが推測できます。
試しに 上記の変換機能を有するシンボル変換ツール(convsym)を作って、冒頭で図を貼った test.s のオブジェクトファイルを変換してリンク&実行してみた結果が下記になります。想定外の TRAP が発生することもなく、正常に終了しています。
L>n:convsym test.o te.o convert test.o to te.o Text:0000000A Data:0000000E Bss:00000006 Symbol:0000007E a001 00000000 a002 00000002 a003 00000006 te.o is created. L>a:lo68 -r -o test.rel te.o L>test.rel L> |
前回の「Pic24MC68Kマイコン(その9)ehBASICの移植」の記事では offset 属性のシンボルがあるとリンクエラーが発生するので ソース内の offset シンボルを全て equ 宣言に書き換えて対応しましたが、元の offset 宣言のソースから作成したオブジェクトファイルを今回作成した convsym ツールで変換後にリンクすることで ehBASIC も問題無く動作しました。^^
equ 宣言ではソースのメンテ性が悪くなるので、ehBASIC のアセンブラソースも offset 宣言に戻しました。
変換時の画面キャプチャが下図になります。変換された offset 属性のシンボル名が値と共に表示されます。
convsym での変換状況 |
|
使用する人は居ないとは思いますが今回作成したシンボル変換ツールも前回記事の末尾で公開しました。
[TOP] [ 前へ ] 連載記事 [ 次へ ]
Pic24MC68Kマイコン(その9)ehBASICの移植 [68K]
MC68Kのチップサイズ(DIP64)と同程度のプリント基板で CP/M-68K を動かす今回の試みに関して前回の記事でケース作成について書きました。
今回作成したものは以前作成した Pic24CPM68K と比べて
速度の評価ということでは BASIC 言語で記述されている ASCIIART.BAS の実行時間を計るのが一般化しつつあります。
しかし、CP/M-68K に付いているデジタルリサーチ社製の CBASIC Compiler ではコンパイルしても実行時間が 1分43秒(103秒)でそれほど速くはありません。CBASICはBCD演算しているので誤差が発生しにくく、当時は会計などの計算によく使われていたようですが、ASCIIART の実行時間は MBASIC 等と比べるとかなり遅く感じます。
68K系の BASIC では Enhanced BASIC が高速なインタープリタとして有名ですが、CP/M-68K 用のものはネットで探しても見つかりませんでした。
また、CP/M-68Kで動作する他の BASIC もないかネットで探してみましたが見つかりませんorz
Enhanced BASIC はソースの入手性も良く、個人ユースであれば自由に配布もできるようなのでありそうで見つからない CP/M-68K へのポーティングを行ってみました。
CP/M-68K のアセンブラは struc やoffset が使えないので(ソース内では offsetが使われている)使用メモリを固定にして ASCIIART.BAS が動作するようになりました。但し、BASIC のソースは コピペできるのでセーブ/ロード機能まではポーティングしていません(細かい動作確認も行っていません)。
★追記 2022/02/06 {
CP/M-68K の アセンブラ(AS68)が offset に対応していました。しかし、offset を使用するとリンク時に下記のエラーが発生して対処方法が不明です。
L>a:lo68 -r -x -o basic68k.rel basic68k.o
: File Format error: Invalid symbol flags = 100100
link68では同様に下記のエラーが発生します。
L>a:link68 basic68k.o
--------------------------------------------------
LINK68 Overlay Linker Release 0.f
Serial No. XXXX-0000 All Rights Reserved
Copyright (c) 1983 Digital Research, Inc.
--------------------------------------------------
basic68k.o
LINK68: INVALID SYMBOL FLAG IN BASIC68K.O, SYMBOL: "ram_strt@"
}
以前作成したPic24CPM68Kと今回のもので実行時間を測定した結果が下表になります。
クロックが倍なのでクロック分で倍速、あとはバス幅が倍になったのである程度速くなるだろうと思っていましたが、更に倍近く(合わせて4倍近く)速くなっています。
Pic24MC68K で実行した時の画面キャプチャが下図になります。コマンドは大文字で入力する必要があります。
今回のポーティングは EASy68K 用のV3.52 のソースから CP/M-68K で動作するものを作り、下記の URL で公開しました。著作権に関してはソース内の記述等を参照してください(商用目的以外で個人使用であれば自由に使用可能)
[history]
*2023/05/08 V3.52c The archive file had a header error, so I recompressed this zip file again. *2022/02/12 V3.52c Fixed a bug that an error occurs in array declaration.
*2022/02/07 V3.52b Returned BSS area declaration from EQU to ds to improve the maintainability
*2022/02/06 V3.52a Memory dynamic allocationSupport & "SYSTEM" command addition
*2022/02/05 V3.52 First public release of CP/M version
★追記 2022/01/07
アセンブラのソース内で offset で宣言したシンボルがリンカーでエラーになる問題への対処として object ファイル内の offset 属性シンボルを EQU 属性に変換するツールを作りました。 object ファイルをこのツールで変換したものをリンカーに掛けると問題無く実行ファイルが作成されます。
詳細は「Pic24MC68Kマイコン(その10)CP/Mアセンブラの謎」の記事を参照して下さい。
★追記 2022/02/13
TeraTerm の TEK4010エミュレーション機能を使って表示した3Dグラフィック画面を貼っておきます。yanataka さんのツイート内容を参考にして試してみました。実行時間は2分34秒でした。
★追記 2022/02/23 {
再帰深度7の場合の出力をテキスト化してみました。TaraTerm の Terminal 設定画面で "Auto switch(VT<->TEK)"をチェックした状態にして下記のリンクからダウンロードしたテキストを表示すると C カーブが表示されます。
}
[TOP] [ 前へ ] 連載記事 [ 次へ ]
今回作成したものは以前作成した Pic24CPM68K と比べて
- クロックが 8MHz から 16MHz に速くなっている
- バス幅が 8bit から 16bit になっている
速度の評価ということでは BASIC 言語で記述されている ASCIIART.BAS の実行時間を計るのが一般化しつつあります。
しかし、CP/M-68K に付いているデジタルリサーチ社製の CBASIC Compiler ではコンパイルしても実行時間が 1分43秒(103秒)でそれほど速くはありません。CBASICはBCD演算しているので誤差が発生しにくく、当時は会計などの計算によく使われていたようですが、ASCIIART の実行時間は MBASIC 等と比べるとかなり遅く感じます。
68K系の BASIC では Enhanced BASIC が高速なインタープリタとして有名ですが、CP/M-68K 用のものはネットで探しても見つかりませんでした。
また、CP/M-68Kで動作する他の BASIC もないかネットで探してみましたが見つかりませんorz
Enhanced BASIC はソースの入手性も良く、個人ユースであれば自由に配布もできるようなのでありそうで見つからない CP/M-68K へのポーティングを行ってみました。
CP/M-68K のアセンブラは struc や
★追記 2022/02/06 {
CP/M-68K の アセンブラ(AS68)が offset に対応していました。しかし、offset を使用するとリンク時に下記のエラーが発生して対処方法が不明です。
L>a:lo68 -r -x -o basic68k.rel basic68k.o
: File Format error: Invalid symbol flags = 100100
link68では同様に下記のエラーが発生します。
L>a:link68 basic68k.o
--------------------------------------------------
LINK68 Overlay Linker Release 0.f
Serial No. XXXX-0000 All Rights Reserved
Copyright (c) 1983 Digital Research, Inc.
--------------------------------------------------
basic68k.o
LINK68: INVALID SYMBOL FLAG IN BASIC68K.O, SYMBOL: "ram_strt@"
}
以前作成したPic24CPM68Kと今回のもので実行時間を測定した結果が下表になります。
ehBASIC での ASCIIART.BAS 実行時間 | |||||||||
|
クロックが倍なのでクロック分で倍速、あとはバス幅が倍になったのである程度速くなるだろうと思っていましたが、更に倍近く(合わせて4倍近く)速くなっています。
Pic24MC68K で実行した時の画面キャプチャが下図になります。コマンドは大文字で入力する必要があります。
Enhanced BASIC での ASCIIART.BAS 実行画面 |
|
★追記 2022/02/06 {
CP/M-68K に移植した ehBASIC で使用メモリを実装メモリに合わせて動的に変更するようにしました(上記追加コメントで書いたように offset コマンドを使用するとリンクでエラーが発生するので EQU で対応)。
また、SYSTEM コマンドで CP/M に戻れるようにしました。
}
CP/M-68K に移植した ehBASIC で使用メモリを実装メモリに合わせて動的に変更するようにしました(上記追加コメントで書いたように offset コマンドを使用するとリンクでエラーが発生するので EQU で対応)。
また、SYSTEM コマンドで CP/M に戻れるようにしました。
|
今回のポーティングは EASy68K 用のV3.52 のソースから CP/M-68K で動作するものを作り、下記の URL で公開しました。著作権に関してはソース内の記述等を参照してください(商用目的以外で個人使用であれば自由に使用可能)
[history]
*2023/05/08 V3.52c The archive file had a header error, so I recompressed this zip file again. *2022/02/12 V3.52c Fixed a bug that an error occurs in array declaration.
*2022/02/07 V3.52b Returned BSS area declaration from EQU to ds to improve the maintainability
*2022/02/06 V3.52a Memory dynamic allocationSupport & "SYSTEM" command addition
*2022/02/05 V3.52 First public release of CP/M version
★追記 2022/01/07
アセンブラのソース内で offset で宣言したシンボルがリンカーでエラーになる問題への対処として object ファイル内の offset 属性シンボルを EQU 属性に変換するツールを作りました。 object ファイルをこのツールで変換したものをリンカーに掛けると問題無く実行ファイルが作成されます。
詳細は「Pic24MC68Kマイコン(その10)CP/Mアセンブラの謎」の記事を参照して下さい。
★追記 2022/02/13
TeraTerm の TEK4010エミュレーション機能を使って表示した3Dグラフィック画面を貼っておきます。yanataka さんのツイート内容を参考にして試してみました。実行時間は2分34秒でした。
TeraTermでのTEK4010端末機能を使ったグラフィック表示例 |
|
★追記 2022/02/16 {
TeraTermのTEK4010端末エミュレーションでグラフィック描画ができるようになったのでタートルグラフィックスで記述されたシェルピンスキーのギャスケットをBASICに移植してみました。自前のスタックでローカル変数を保存してリカーシブコールしています。
ULproject さんの VL-BASIC の説明サイトの「有名なフラクタル図形のシダを描く」のページで紹介されているフラクタル図形のシダを ehBASIC で描いてみました。
}
TeraTermのTEK4010端末エミュレーションでグラフィック描画ができるようになったのでタートルグラフィックスで記述されたシェルピンスキーのギャスケットをBASICに移植してみました。自前のスタックでローカル変数を保存してリカーシブコールしています。
シェルピンスキーのギャスケット |
|
ULproject さんの VL-BASIC の説明サイトの「有名なフラクタル図形のシダを描く」のページで紹介されているフラクタル図形のシダを ehBASIC で描いてみました。
フラクタル図形 シダの葉 |
|
★追記 2022/02/18 {
自己相似フラクタルの有名どころであるレヴィのC曲線を描いてみました。C曲線自体の記述部分は極めて単純ですね。相変わらず上下逆のままですw(bmpファイルも中身が上下逆だけどテクトロ端末等の影響なのかな?)
}
自己相似フラクタルの有名どころであるレヴィのC曲線を描いてみました。C曲線自体の記述部分は極めて単純ですね。相変わらず上下逆のままですw(bmpファイルも中身が上下逆だけどテクトロ端末等の影響なのかな?)
Levy C curve |
|
★追記 2022/02/23 {
再帰深度7の場合の出力をテキスト化してみました。TaraTerm の Terminal 設定画面で "Auto switch(VT<->TEK)"をチェックした状態にして下記のリンクからダウンロードしたテキストを表示すると C カーブが表示されます。
}
★追記 2022/02/24 {
自己相似フラクタルでは最も有名と思われるドラゴンカーブを描いてみました。かなり前に ASCII 誌に掲載された BASIC プログラムを真似てドットインパクトプリンタで出力した記憶があります。
}
自己相似フラクタルでは最も有名と思われるドラゴンカーブを描いてみました。かなり前に ASCII 誌に掲載された BASIC プログラムを真似てドットインパクトプリンタで出力した記憶があります。
Dragon Curve |
|
[TOP] [ 前へ ] 連載記事 [ 次へ ]
Pic24MC68Kマイコン(その8)ケース作成 [68K]
前回の記事で MC68000 の DIP64 チップサイズとほぼ同じサイズの基板で CP/M-68K が動作することを書きましたが、今回はケースについて書いてみます。
プリント基板が小さくまとまったのでケースも小さくしようとするとインサートナットを入れる場所が無くなってしまいました。そこで今回は PETG フィラメントの柔軟かつ積層間の結合強度が高いという特徴を生かしてネジを使わないかみ合わせ方式でのキャップの固定を試みてみました。
CAD で表示した全体像が下図になります。最初はボディー部前面に「Pic24MC68K」のロゴ入れていましたが、3D プリンタで出力すると文字出力の影響で裏側にも薄い縞模様が現れるのでロゴは削除しました。
今回作成したケースの主要な部分について以下に記載したいと思います。まず、プリント基板のサポート方法についてですがいつものようにケース内部の側面に溝を付けることで実現しています(最近設計した基板には四隅に取付け用の穴を設けていません)。
次に冒頭でも書いたネジを使わないキャップの固定についてですが下図のようにキャップの上面の切り口を斜面にして下側はケース内部に設けた溝に嵌るようにしました。下側には取り外し用の溝も付けています。
リセットスイッチに関しては今回最も悩んだ箇所になりますが試行錯誤の結果、下図のように C リング(上側の板状の部分)に似たような方式にしてみました。
プリント基板をケースに入れる前にスイッチポールを入れて、プリント基板が入った後に C リングもどきで固定します。
Cリングもどきの左の側面はケースの内面に合わせて斜面になっていて取付後の回転防止になっています。
それでは3Dプリンタで出力した実際のケースを確認していきます。LED 用の窓を省略するために PETG の透明なフィラメントで造形し、透明度を上げるために GSIクレオス Mr.スーパークリアー UVカット 光沢 スプレー を塗布しました。
下の写真が USB コネクタ部です。ピッタリですね^^
下の写真がケース内にプリント基板を入れた状態のものです。写真では判り辛いですが、基板設計CADから引き継いだ3Dデータを使って設計しているので当然ですがピッタリのサイズです( 0.2mm 程度のマージンを入れて設計しています)
下の写真がリセットスイッチ部をズームしたものでケースの外側から押すとカチッと音がして反応し、なかなかいい感じです。
下の写真はキャップ部分をアップしたものです。写真からは見えにくいですが SDカード用のスリットも大きさ及び位置が共にピッタシです^^
問題のキャップのかみ合わせ部分が下の写真になります。ネジも無く一体化していて分離できる部品であることすら判らないくらいです。
下の写真がトップ面です。UV カットを塗布していますが、薄っすらと MC68K のチップが見える程度の透明度です(SLA方式の3Dプリンタで出力すればもっと透明になりますが、強度が弱くてケースには使いにくい)。
ボトム面が下の写真です。造形時に発生した糸引きの後が見えますが見た目は写真程は目立ちません。
最後に CP/M-68K が動作中の写真です。バスリクエストにより緑の LED が点灯しています。
★追記 2022/02/02
リセットスイッチ部分で悩んだと書きましたが、没になった案の一例として楔型結合タイプのものの写真を追記します。
機能的には問題無かったのですが、組立と分解時の作業が大変なので採用しませんでした。細かな部品ですが 0.4mm のノズルでも結構出力できるものですね。
[TOP] [ 前へ ] 連載記事 [ 次へ ]
プリント基板が小さくまとまったのでケースも小さくしようとするとインサートナットを入れる場所が無くなってしまいました。そこで今回は PETG フィラメントの柔軟かつ積層間の結合強度が高いという特徴を生かしてネジを使わないかみ合わせ方式でのキャップの固定を試みてみました。
CAD で表示した全体像が下図になります。最初はボディー部前面に「Pic24MC68K」のロゴ入れていましたが、3D プリンタで出力すると文字出力の影響で裏側にも薄い縞模様が現れるのでロゴは削除しました。
Pic24MC68Kケース外観 |
|
今回作成したケースの主要な部分について以下に記載したいと思います。まず、プリント基板のサポート方法についてですがいつものようにケース内部の側面に溝を付けることで実現しています(最近設計した基板には四隅に取付け用の穴を設けていません)。
プリント基板のサポート |
|
次に冒頭でも書いたネジを使わないキャップの固定についてですが下図のようにキャップの上面の切り口を斜面にして下側はケース内部に設けた溝に嵌るようにしました。下側には取り外し用の溝も付けています。
キャップの固定方法 |
|
リセットスイッチに関しては今回最も悩んだ箇所になりますが試行錯誤の結果、下図のように C リング(上側の板状の部分)に似たような方式にしてみました。
プリント基板をケースに入れる前にスイッチポールを入れて、プリント基板が入った後に C リングもどきで固定します。
Cリングもどきの左の側面はケースの内面に合わせて斜面になっていて取付後の回転防止になっています。
リセットスイッチ部 |
|
それでは3Dプリンタで出力した実際のケースを確認していきます。LED 用の窓を省略するために PETG の透明なフィラメントで造形し、透明度を上げるために GSIクレオス Mr.スーパークリアー UVカット 光沢 スプレー を塗布しました。
下の写真が USB コネクタ部です。ピッタリですね^^
USBコネクタ部 |
|
下の写真がケース内にプリント基板を入れた状態のものです。写真では判り辛いですが、基板設計CADから引き継いだ3Dデータを使って設計しているので当然ですがピッタリのサイズです( 0.2mm 程度のマージンを入れて設計しています)
ケース内のプリント基板 |
|
下の写真がリセットスイッチ部をズームしたものでケースの外側から押すとカチッと音がして反応し、なかなかいい感じです。
リセットスイッチ部 |
|
下の写真はキャップ部分をアップしたものです。写真からは見えにくいですが SDカード用のスリットも大きさ及び位置が共にピッタシです^^
キャップ部分 |
|
問題のキャップのかみ合わせ部分が下の写真になります。ネジも無く一体化していて分離できる部品であることすら判らないくらいです。
キャップのはめ込み状態 |
|
下の写真がトップ面です。UV カットを塗布していますが、薄っすらと MC68K のチップが見える程度の透明度です(SLA方式の3Dプリンタで出力すればもっと透明になりますが、強度が弱くてケースには使いにくい)。
Pic24MC68K ケース(トップ面) |
|
ボトム面が下の写真です。造形時に発生した糸引きの後が見えますが見た目は写真程は目立ちません。
Pic24MC68K ケース(ボトム面) |
|
最後に CP/M-68K が動作中の写真です。バスリクエストにより緑の LED が点灯しています。
Pic24MC68K 動作中の状態 |
|
★追記 2022/02/02
リセットスイッチ部分で悩んだと書きましたが、没になった案の一例として楔型結合タイプのものの写真を追記します。
機能的には問題無かったのですが、組立と分解時の作業が大変なので採用しませんでした。細かな部品ですが 0.4mm のノズルでも結構出力できるものですね。
リセットボタン部の未採用案の例 |
|
[TOP] [ 前へ ] 連載記事 [ 次へ ]