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

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

[第131回]


●LF(Line Feed、コード0AH)その2

前回、LF(0AH)についていろいろ書きました。
LF(改行)というそもそもの動作から考えて、そして通常はCR(Carriage Return、コード0DH)とペアにして使うことによって、復帰改行(復改と略すこともあります)を実現することから考えて、LFはカーソルがその位置のまま1行下に移動するものと解釈していました。
たとえばカーソルが画面左端になくて、画面の途中にある場合にLFコードを画面に出力すると、カーソルは画面左端に移動しないで画面途中のポジションのまま1行下に移動する、と考えていました。

ところが前回簡単なC++プログラムを作ってテストをしてみた結果、LF(0AH)だけを画面に出力しても、カーソルは画面左端に移動するとともに改行が行なわれてしまいました。
どうやら私が考えていたLFの動作とは異なっているようです。
いろいろ調べてみますと、OSによっても相違があるらしいとのことでした。

ちょっと納得はできませんが、実際にC++プログラムでもそういう動きをすることが確かめられたわけですから、やはりLF(0AH)はその1コードだけで復帰と改行の両動作をしてしまう、と考えることにした方がよさそうです。
C++で(Cでも)普通は復帰改行をする場合に¥nを使いますが、これは0AHのことなのだ、ということにも気が付きました。

しかし私は古い人間ですから、そういうことがわかってしまっても、マシン語で復帰改行をするプログラムを書くときは、やっぱりCRLF(0D・0A)と書くことにします、というようなことを書きました。

0AHだけで復帰改行動作をしてしまうとしても、0Dはあくまで復帰だけの動作ですから、CRLFと書くことで、結果として復帰復帰改行という動作になってしまったとしても、特に支障はないと思います。

以上、前回のLFについての項はそういう内容だったのでありますが。
一晩寝ますと脳細胞がリフレッシュされまして、そのときは見えなかったものが見えてくるようになります。
今朝になりましてから、前回の、そのくだりを読んでいましたら。
その結論は、ちょっとおかしいのではないの?
ということに気がつきました。

確かにC++プログラムで試してみた結果は、LFのみで復帰改行動作をすることが確認できたわけですが。
もともとC++(もしくはC)では¥n(0AH)だけで復帰改行してしまうわけで。
それってつまり、コンパイラがそのような動作をするようなマシン語のプログラムを生成してしまう、ということではありませんか?

おおお。
そこには気が付かなかった。
それはやっぱり検証してみなければ。

どうするか?
そりゃあ、そこまできたら、やっぱりマシン語で確認してみるしかありませんでしょう。

こちらは前回作ったLFをテストするC++プログラムを、8086アセンブラ用に書き直したプログラムです。

; LF test
;
        ORG=100
;
        MOV AH,02
        MOV DL,0D
        INT 21
        MOV DL,0A
        INT 21
        MOV DL,61
        MOV DH,06
LOOP:INT 21
        INC DL
        DEC DH
        JNZ LOOP
        MOV DL,0A
        INT 21
        INT 21
        INT 21
        MOV DL,41
        INT 21
        RET
;

CP/Mでは、画面に1文字を表示するのにファンクションコール02を使いますが、MSDOSでは同じことをシステムコール02を使って行ないます。
CP/Mでは、C=02、E=文字コードとしたうえで、0005Hをコールします。
MSDOSではAH=02、DL=文字コードとしたうえで、INT 21を実行します。
こういうところが、よくMSDOSがCP/Mを下敷きにして作られたと言われる所以です。

さて、これを。
私が昔に作った8086アセンブラでマシン語に変換します。
必要なものはなんでも自分で作ってしまいます。
私が自分で作ったアセンブラですから、変な細工は一切していません。
純粋、混じりっけなしで、1対1のマシン語コードを生成します。
これは、今回、最強の武器なのではありませんか?

アセンブル後、直ちに実行してみましたところ、結果はこのようになりました。



おおお。
LF(0AH)だけでは復帰していないじゃありませんか!!!
やっぱり以前から私が考えていた通りだったのです。
純粋なマシン語のプログラムでは、復帰改行には、0AHだけではだめで、0DHと0AHを送る必要がありました。
いやあ。
納得。

あ。
参考までに。
上記のソースプログラムをアセンブルして得られるアセンブルリストを下に示しておきましょう。

2012/5/26  10:2  DOSLFTST.TXT
[00001]                     ; LF test
[00002]                     ;
[00003]                         ORG=100
[00004]                     ;
[00005] 0100  B402              MOV AH,02
[00006] 0102  B20D              MOV DL,0D
[00007] 0104  CD21              INT 21
[00008] 0106  B20A              MOV DL,0A
[00009] 0108  CD21              INT 21
[00010] 010A  B261              MOV DL,61
[00011] 010C  B606              MOV DH,06
[00012] 010E  CD21          LOOP:INT 21
[00013] 0110  FEC2              INC DL
[00014] 0112  FECE              DEC DH
[00015] 0114  75F8              JNZ LOOP <010E>
[00016] 0116  B20A              MOV DL,0A
[00017] 0118  CD21              INT 21
[00018] 011A  CD21              INT 21
[00019] 011C  CD21              INT 21
[00020] 011E  B241              MOV DL,41
[00021] 0120  CD21              INT 21
[00022] 0122  C3                RET
[00023]                     ;
0100-0122
LOOP         =010E  

私は、マシン(ハード)を本当に知るためには、Cなどでは駄目で、やっぱりマシン語を知ることが必要なのだ、というのが持論なのですが(それは時流に逆らった古い考えのようにとらえられてしまうでしょうけれど)、こういうことを経験しますと、やっぱりCなどでは本当のことはわからない、ということをあらためて実感いたします。
皆様はどのようにお考えになりますでしょうか?

そういえば。
C++プログラムでLFのテストを行なう前に、BSについても同様にC++プログラムで行ないました。
せっかく8086アセンブラでLFについてのテストを行なったこの機会に、BSについてもテストをしておきましょう。
なに。
簡単なことです。
コード0AHをコード08Hに変更するだけですから。

こちらがそのように変更したアセンブラソースプログラムです。

; BS test
;
	ORG=100
;
	MOV AH,02
	MOV DL,0D
	INT 21
	MOV DL,0A
	INT 21
	MOV DL,61
	MOV DH,06
LOOP:INT 21
	INC DL
	DEC DH
	JNZ LOOP
	MOV DL,08
	INT 21
	INT 21
	INT 21
	MOV DL,41
	INT 21
	RET
;

こちらはそれを8086アセンブラでアセンブルして作成された、アセンブルリストです。

2012/5/26  10:11  DOSBSTST.TXT
[00001]                     ; BS test
[00002]                     ;
[00003]                         ORG=100
[00004]                     ;
[00005] 0100  B402              MOV AH,02
[00006] 0102  B20D              MOV DL,0D
[00007] 0104  CD21              INT 21
[00008] 0106  B20A              MOV DL,0A
[00009] 0108  CD21              INT 21
[00010] 010A  B261              MOV DL,61
[00011] 010C  B606              MOV DH,06
[00012] 010E  CD21          LOOP:INT 21
[00013] 0110  FEC2              INC DL
[00014] 0112  FECE              DEC DH
[00015] 0114  75F8              JNZ LOOP <010E>
[00016] 0116  B208              MOV DL,08
[00017] 0118  CD21              INT 21
[00018] 011A  CD21              INT 21
[00019] 011C  CD21              INT 21
[00020] 011E  B241              MOV DL,41
[00021] 0120  CD21              INT 21
[00022] 0122  C3                RET
[00023]                     ;
0100-0122
LOOP         =010E  

このテストプログラムを実行してみた結果は、以下のようになりました。



BSについてはC++プログラムでもマシン語のプログラムでも同じ結果になりました。

今回はファンクションコール0Aについて、前回の続きを書くつもりでしたが、LFについてマシン語プログラムを作って試してみることを思いついてしまいましたので、予定を変更いたしました。
ファンクションコール0Aの続きにつきましては、次回に書くことにいたします。

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

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