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の変数の領域。
ちょっと脱線するがBASICソース中の文字を書き換えることが可能。
MID$を実行した後はA$の内容を書き換えた結果が新しい変数の領域に置かれている。これはA$の内容をいったん作業領域にコピーした後で加工し、文字列が置かれている番地を更新しているものと思われる。そうすると動作は以下のとおり。
(1)まずA$の内容を作業領域にコピーし、(2)作業領域に対してMID$(work$,2)=A$相当の書き換えを行い、(3)A$のVARPTRで参照される文字列格納アドレスを作業領域の先頭番地に書き換える。
Z80や8086での動作は以下のように考えられる。(1)作業領域へのコピーは同じだが、(2)先にA$の情報を書き換えてしまうので、(3)の置き換え動作で"11111"となってしまう。
MID$(A$,2)=A$はこのケースに該当するが、領域が一部かぶるデータのコピーは転送元と転送先の位置関係からアドレスの前からやるか後ろからやるか決めないと正しく行われない。昔のパソコンはコードをできるかぎり削りたいためそのような条件の判断とコピー動作の切り替えはやっていないと思われる。そもそもA$を最初に定義した状態では文字列がBASICのソースの中にあるので直接書き換えることはできずどこかにコピーして作業しないといけない。
富士通のF-BASICは最初から"11234"と期待される動作をしており、80386(FM-TOWNS)のF-BASIC386でも同じ結果だが、Windows上で動作するF-BASIC V6.3はN-88BASICとの互換性を意識しているため"11111"となっている。
以上、BASICの中身は見ずに動作だけから考えてみました。




