まごころせいじつ堂

浜町庄金 研究開発  マイコンで遊んでばっかりで

BASIC

BASICの左辺MID$の動作について

 BASICの文字列関数MID$()は文字列から指定した場所を抜き出して返す関数だけど、左辺に置くことで文字列の特定の位置からの置き換えをすることができる。これはMicrosoft系のBASICにある機能で初期のもの、サブセットと思われるものには実装されていない。書式は

MID$(文字変数名,文字位置,[文字数])=文字式

で、文字変数名の中の文字列について文字位置から文字数分だけ文字式の内容で置き換える。
これについて、文字変数名と同じもので置き換えようとすると結果が異なるものがある。

A$="12345" : MID$(A$,2)=A$

この結果、A$が"11234"になるものと"11111"になるものがある。各機種について検証した結果は @1re1 さんが BASIC言語 MID$ステートメント 実行結果一覧.xlsx - Microsoft Excel Online としてまとめてくださっている。また、MID$の歴史的経緯については ときどきの雑記帳 Re* にて調査されている。

 では実機での挙動からどのような動作をしているのか調べていく。
VARPTR()関数は指定した変数の情報を返す。文字型変数の場合は文字列の長さ(1バイト)、文字列の格納アドレス(2バイト)を保存しているアドレスを返す(格納アドレスのエンディアンはCPUに依存)。以下の実行例ではA$の文字列がMID$実行後に2103番地から32760番地に変化している。かなりアドレスが離れているが、2103番地はBASICのソーステキスト内、32760番地はBASICの変数の領域。
2023-04-19 03.54.44

 ちょっと脱線するがBASICソース中の文字を書き換えることが可能。
2023-04-20 21.58.02

 MID$を実行した後はA$の内容を書き換えた結果が新しい変数の領域に置かれている。これはA$の内容をいったん作業領域にコピーした後で加工し、文字列が置かれている番地を更新しているものと思われる。そうすると動作は以下のとおり。
(1)まずA$の内容を作業領域にコピーし、(2)作業領域に対してMID$(work$,2)=A$相当の書き換えを行い、(3)A$のVARPTRで参照される文字列格納アドレスを作業領域の先頭番地に書き換える。
スクリーンショット 2023-05-11 22.02.48

 Z80や8086での動作は以下のように考えられる。(1)作業領域へのコピーは同じだが、(2)先にA$の情報を書き換えてしまうので、(3)の置き換え動作で"11111"となってしまう。
スクリーンショット 2023-05-11 22.03.08

 MID$(A$,2)=A$はこのケースに該当するが、領域が一部かぶるデータのコピーは転送元と転送先の位置関係からアドレスの前からやるか後ろからやるか決めないと正しく行われない。昔のパソコンはコードをできるかぎり削りたいためそのような条件の判断とコピー動作の切り替えはやっていないと思われる。そもそもA$を最初に定義した状態では文字列がBASICのソースの中にあるので直接書き換えることはできずどこかにコピーして作業しないといけない。

 富士通のF-BASICは最初から"11234"と期待される動作をしており、80386(FM-TOWNS)のF-BASIC386でも同じ結果だが、Windows上で動作するF-BASIC V6.3はN-88BASICとの互換性を意識しているため"11111"となっている。


以上、BASICの中身は見ずに動作だけから考えてみました。




豊四季タイニーBASICをMS-DOS上で動かす

 豊四季タイニーBASICのソースをコンパイルしてMS-DOS上で動かしてみる。

 きっかけは生の8086上で色々動かせるための環境をどうしようかと考えていてそういえば学生の頃からよく使ったLSI-C86試食版があったな、と。Windows10やWindows7では16bit版のバイナリは実行できないのでこれはMS-DOS Player for Win32-x64を使い、確認のため豊四季タイニーBASICをコンパイルして実行してみた。

以上でだいたいわかった方はこちらをどうぞ↓


(1)LSI-C86試食版のインストール
エル・エス・アイ ジャパン株式会社のフリーソフトウェア集のページからlsic330c.lzhをダウンロードし、.LZH形式が展開できるツールでC:\LSIC86以下に展開。
C:\BIN以下にある_LCCの内容を修正。昔はPC-98だったのでA:ドライブだったよな〜等

# LSI C-86 compiler's configuration file

-DLSI_C
-XC:\LSIC86\BIN -LC:\LSIC86\LIB -IC:\LSIC86\INCLUDE -T -O
-acdos.obj $LSICOPTS
&               #Command line argument will be inserted here
-lknjlib -ldoslib -v
C:\LSIC86\BINにパスを通す。[システムのプロパティ]→[環境変数(N)…]からシステム環境変数のPathにC:\LSIC86\BINを追加。

(2)MS-DOS Playerの導入
 MS-DOS Player for Win32-x64からダウンロード。MS-DOSを実行するプロセッサが8086/80286/80386/80486から、コマンド自体が動作する環境が32bit/64bitから選べる。LSI-C86は8086以降から動くのでどれを選んでも問題ない。動作環境はWindows10だと64bit版。これに対応したMSDOS.EXEをC:\LSIC86\BIN以下にコピーする。
 ここまでで適当にhello.cなど書いて動作確認。16bitバイナリの実行には頭にMSDOSを付けて実行。

C:\LSIC86> MSDOS LCC HELLO.C

私の環境では普段使っているデスクトップのWindows10機ではウイルススキャンの対象になっているのかうまく動かなかった。WindowsXP→Windows7→Windows10と継ぎ足しで使ってて切り分けも面倒なので別のパソコンで動かしている。

(3)豊四季タイニーBASICの修正
 豊四季タイニーBASICArduino版をベースにコンパイルできるよう修正する。
変更点:
(1) ソースの文字コードをSJISに変換
(2) コメント//を/* */の形式に変換
(3) #define STR_EDITIONを"MSDOS"に
(4) Terminal controlの部分をputch(c) getch() kbhit() に
(5) (uintptr_t)を削除。これArduino Dueで豊四季タイニーBASICを動かそうとした時に追加して反映してもらったパッチなのですが外すことに。
(6) getrnd()再実装。これはarduinoのrandom(MAX,MIN)とrand()の仕様が違うため。
(7) BYE命令追加。一度basicを起動するとMS-DOSに戻る手段がなかったのでNEWとかRUNといった命令を参考に呼んだらexit()を実行するようにした。
(8) 末尾にbasic()を呼び出すmain()関数追加。

配列の上限やらそのあたりはいじっていません。


 さて今後ですが、具体的にはV20SBC開発環境として使えないかどうか探っていきます。LSI-C86製品版なら組み込み向けのリンクもできるらしいし、BANDAIの携帯ゲーム機WonderSwanの開発環境WonderWitchにはカスタマイズしたLSI-C86が付属していたのですがどこにしまったかな?

案1:通常のMSDOS向けにリンクしてある.objについて、適切にハードウェアの初期化を行った.objファイルを生成しリンク
案2:豊四季タイニーBASICからMS-DOSやその他ライブラリに依存した部分(入出力とrand()、exit() )を修正してアセンブラ1本にし、他の8086ターゲットアセンブラに持っていく
案3:組み込み向けの使用例があるTurbo-Cあたり 海外の事例探し

 といった感じで。




CUI32Stem届いた

 SeeedStudioで扱っているPIC32MXマイコンボードCUI32Stemが届いた。$29.95で日本向けの送料は無料。注文から約10日。急ぎの便もある。

SeeedStudio CUI32Stem

 あれえ、今注文したらピンヘッダが付いてるじゃない。

CUI32Stemは、80MHz/512K Flash/128K RAMのPIC32MX795F512Hを搭載した名刺サイズのマイコンボード。で、BASICインタプリタを搭載している。開発キットは特に必要なく、端末となるパソコンがあればOK。
その他の特徴は:
8 DMA Channels
3 SPI
4 I2C
6 UART (serial ports)
Full Speed USB 2.0 Device or Host mode
16 A/D channels, 10-bit resolution

電源はUSBコネクタまたは電源端子から(スイッチ切り換え)。USBはホストモードもある(スイッチ切り換え、コネクタ未実装)。
電源LEDは赤。動作中を示すHertBeat用の緑LEDはpin RE0に接続されている。
タクトスイッチはRESETとpin RE7に接続されているPROGボタンがある。
システムクロックは8MHzのX'tal。RTCC用の水晶はついていない。

開発元:
OVERTONE Labs

Wiki:
seeed wiki CUI32Stem

使い方:
StickOS™ BASIC User's Guide, v1.90

2012CUI32stem


ではMacOSXに接続して遊んでみよう。mini-BのUSBケーブルでCUI32Stemを接続し、ターミナルを開く。
ls /dev/tty.* でシリアルポートを確認し、screenコマンドで接続する。
例:screen /dev/tty.usbmodem621
リターンキーを一回押すとプロンプトが出てくる。あとはBASIC。

ではprogボタンを押すと現在のtick値を表示するプログラムを作ってみる。

 
  10 dim prog as pin re7 for digital input
  20 while 1 do
  30   if prog==0 then
  40     print ticks
  50   endif 
  60 endwhile 
行番号とともに打ち込んだ後、run。基板上のprogボタンを押すと表示される。

次はFizzBuzz。サブルーチンには引数を渡せる。


  10 dim i
  20 for i = 1 to 100
  30   gosub fizzbuzz i
  40 next 
  50 end 
 100 sub fizzbuzz n
 110   if n%3==0 then
 120     if n%5==0 then
 130       print "FizzBuzz"
 140     else 
 150       print "Fizz"
 160     endif 
 170   elseif n%5==0 then
 180     print "Buzz"
 190   else 
 200     print n
 210   endif 
 220 endsub 
ちょっと試してみたが面白い。昔BASICで遊んだことのある人はすぐ慣れると思う。BASICの文法は変数の宣言が必要で、式はC言語に似てて、ちょっと厳格になった感じ。また変数はすべて配列扱いで通常は変数名[0]が参照される。

そうねえ、印象としてはむき出しのプチコン。
 
記事検索
プロフィール

hardyboy

カテゴリ別アーカイブ
月別アーカイブ
QRコード
QRコード
  • ライブドアブログ