2012.5.22
前へ
次へ
ホームページトップへ戻る

復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります

[第127回]


●BS(Back Space)についてわかったこと(その2)

前回からの続きです。
[BS]キーの動作は皆様ご存知の通り、1文字前に戻って、そこに表示されている1文字を消去する、という動作です。
[BS]キーの文字コードは08Hです。
08Hは画面表示のためのディスプレイコードとしても使われています。
画面表示の場合にも、BSとして働きます。
というように、ごく当たり前に認識していたのですけれど。

ところが。
コード08Hはキー入力の場合と画面表示の場合とでは、動作が異なっているのです。
ご存知でしたか?
私はそんなこと、全く考えたこともありませんでした。
画面に表示する場合でもごく普通にキー入力のときと同じ動作をするものだとばかり思っていました。

ND80ZVに移植したCP/M2.2でも[BS]が期待した通りに動きだしましたものですから、さらに進んであれこれ[BS]の動作を確認していましたら、そのことに気が付いてしまったのです。

CP/M2.2の上で動作する簡単なプログラムを作って試してみました。

2012/5/19  12:3  bstest.txt
END=8120
              ; BS test
              ;
              	ORG $8100
              	FCALL=$8005
              	B_CONOUT=$D20C
              ;
8100 1E61     	LD E,61;a
8102 1606     	LD D,06
8104 0E02     LOOP:LD C,02
8106 D5       	PUSH DE
8107 CD0580   	CALL FCALL
810A D1       	POP DE
810B 1C       	INC E
810C 15       	DEC D
810D C20481   	JP NZ,LOOP
8110 0E08     	LD C,08;BS
8112 1603     	LD D,03
8114 CD0CD2   LOOP2:CALL B_CONOUT
8117 15       	DEC D
8118 C21481   	JP NZ,LOOP2
811B 0E41     	LD C,41;A
811D CD0CD2   	CALL B_CONOUT
8120 C9       	RET
              ;
B_CONOUT     =D20C  FCALL        =8005  LOOP         =8104  
LOOP2        =8114  

ファンクションコール02(コンソール出力)を使って61H〜66H(’a’〜’f’)を画面に表示し、次にBIOSのコンソール出力ルーチンで08H(BS)を3回出力し、最後に41H(’A’)を画面に出力します。
08Hを出力するのにBIOSのコンソール出力ルーチンを使ったのは、ファンクションコールでは何か細工がされているかもしれないと考えたからです。

でも念の為、08Hを出力するところもファンクションコール02を使ったプログラムも作りました。

2012/5/19  12:4  bstest2.txt
END=8124
              ; BS test
              ;
              	ORG $8100
              	FCALL=$8005
              	B_CONOUT=$D20C
              ;
8100 1E61     	LD E,61;a
8102 1606     	LD D,06
8104 0E02     LOOP:LD C,02
8106 D5       	PUSH DE
8107 CD0580   	CALL FCALL
810A D1       	POP DE
810B 1C       	INC E
810C 15       	DEC D
810D C20481   	JP NZ,LOOP
8110 1E08     	LD E,08;BS
8112 1603     	LD D,03
8114 0E02     LOOP2:LD C,02
8116 D5       	PUSH DE
8117 CD0580   	CALL FCALL
811A D1       	POP DE
811B 15       	DEC D
811C C21481   	JP NZ,LOOP2
811F 0E41     	LD C,41;A
8121 CD0CD2   	CALL B_CONOUT
8124 C9       	RET
              ;
B_CONOUT     =D20C  FCALL        =8005  LOOP         =8104  
LOOP2        =8114  

あれ?
今、気がつきましたが、最後に’A’を表示するところは、ファンクションコール02ではなくて、BIOSのコンソール出力をコールしていますね。
まあ、でもここのところはどちらを使っても結果は同じになります。

さて。
このプログラムを実行したら、結果はどのように表示されると思います?
そりゃあ、最初にabcdefと表示して、次にBSを3回行って、最後にAを表示させるんだから、
abcA
と表示されるんでしょ?

ええ。
私はごく普通に、そのように表示されるものだとばかり思っていました。
ところが。
結果はそうではありませんでした。

下はND80ZVに修正後のCP/M2.2をインストールして、ZB3.EXEも修正後のZB3N.EXEを使って、上の2つのテストプログラムを実行させたときの画像です。



abcAef
と表示されてしまいました。
なんと。
コード08Hを画面に送ると[BS]ではなくて[←]として働いてしまいます。

しかし、これはCP/Mのせいではありません。
だからわざわざBIOSのコンソール出力ルーチンも使ってみたのです。
BIOSのコンソール出力ルーチンは、何も余計なことはしないで、画面表示コードをWindows側のプログラム(ZB3.EXE)にそのまま送るだけです。

それじゃあ、ZB3.EXEで何か細工をしてるんじゃないの?
ええ、自分で作ったプログラムですけれど、私もそこのところは、ひょっとしたらと思ったものですから、ZB3.EXEを離れてごく簡単な画面表示のプログラムをC++で作って試してみました。
こちらはごく簡単な普通のC++プログラムですから、皆様も試してみてくださいませ。

// BStest
//
#include <stdio.h>
//
void main()
{
	printf("abcxyz");
	printf("%c%c%cA\n",0x08,0x08,0x08);
}


これをBorland C++ Conpiler5.5でコンパイルしてMSDOSプロンプトで実行してみました。



全く同じ結果になりました。
abcAyz
と表示されています。
やっぱり08Hは画面に表示させるときは、[←]の動作をするようです。

あ。
上の画面はWindows98SEでの実行画面です。
だからじゃないの?
その疑問はもっともです。

ですので、Windows7でも試してみました。



Windows7でも同じ結果になりました。

しかし。しかし。
これは現在のWindowsだからこのような動作になるので、CP/Mが現役だったころのパソコンでは、またそれとは違った動作だったのではありませんか?
ま。
それも、もっともな疑問です。
しかし、実はそのことについては、今も昔も同じだったと思いますよ。
なぜかといいますと。

これは[第125回]でお見せした、CP/M2.2のソースプログラムの[BS]の処理をしているところの一部です。



なにやらややこしいことをやっているようですが、なにをやっているのか、おわかりになりますでしょうか。
ここで ’ ’は20H、BSは08Hです。
CONOUTはBIOSのコンソール出力です。

最初にBS(08H)をコンソール出力して、次にスペース(20H)を出力して、最後にまたBS(08H)を出力しています。
もしも昔のパソコンの画面表示で08Hが単純に[BS]の動作をするということでしたら、こんな面倒なことをしなくても、そのまま08Hをコンソール出力するだけで済んだはずです。
CP/Mのソースプログラムがこのように書かれていることこそ、今も昔も画面に表示するときの08Hは[BS]ではなくて[←]であることの、なによりの証拠だと思います。
ううう。
知らなかったなあ…。

さて、そういうことになりますと。
今や確定的事実として、08Hはキー入力と画面表示では、異なる動作をすることがわかってしまいました。
というよりも、キー入力のエコーのときだけわざわざ[BS]の動作をさせている、ということのようです。

ただ単にコード08Hをコンソール出力するときは[←]の動作になります。
しかし、ファンクションコール01でコンソール入力を行なったときは、キー入力コードを受取ると同時に、そのコードを画面にエコー表示するためにコンソール出力も行ないます。
ファンクションコール01で[BS](08H)を受取ったときは、エコーとして[BS]の動作、つまり1文字後退してそこに表示されている1文字を消去する、という動作をさせなければなりません。
なかなかに面倒なことです。

私は今までそんなふうには考えてなくて、いつも08Hは1文字後退1文字削除、だとばかり思い込んでしまっていましたから、CP/M互換DOSもその考えをもとにしてプログラムを書いてしまいました。
当然のことながら。
そこのところは、またまたそのように直さなければなりません。

ええ。
仕方がありませんねえ。
そのようにしなければなりませんから。
ぶつぶつ文句を言いながら、直してしまいました。

ところが。
実は、そんなことでは、終わらなかったのでありますよ。
かくて、長い長い1日となってしまったのでありました。

ワンボードマイコンでCP/Mを![第127回]
2012.5.22upload

前へ
次へ
ホームページトップへ戻る