OSを作れたらいいねぇPart2

2:まずはキー反応のタイミング
hideyosi 10/24 09:45
さてさて。まずは、キーボードのボタンの反応。
いままでは、キーを「離した」時に反応するようにしてあった。
(これは深い意味はありません。なんとなくでした)
該当部分はここ。

--------------------------------------------------------
;乗っ取ったキーボード割り込み部分
IINT09:

;押されたキーは何かを調べる
;IN命令で、押されたキーの値を取得
MOV DX,0x60
IN AL,DX


;持ってきた値を一時、AHに複製する
MOV AH,AL
;AHに複製した値の7ビット目だけを摘出
AND AH,0x80
;もし、この結果の値が00000000すなわち0x0なら、
;キーは「押された」となるはず。ここで条件分岐
CMP AH,0x0

;なにもせずに割り込みを終了する
JE INTEND

------------------------------------------------------

ここを、10000000、すなわち0x80だった時に反応すればいいように
すればいいわけだね。

CMP AH,0x80

コンパイルしてと・・・

お!? 確かに、なんか反応がよくなったぞ!? 

3:続いてキー判定部
hideyosi 10/24 10:07
前回のコード。
私は、キーボードスイッチと文字コードとの対応を、CMP、JEで、だーーーっと書いた。まあ、あれでも動くから問題ないっちゃぁないんだけど、なんかカコワルイし、書くのも大変。
そんなのを晒していたら、Kタンがこんな参考コードをくれた。

---------------------------------------------------------
; ALには0x1eなどのコードが既に入っているとする。

  MOV BH,0
  MOV BL,AL
  MOV AL,[BX+table]

; これでもうALには文字コードが入っている。たくさんのCMP+JEにさようなら。

; 以下はプログラムではなくデータなので間違って実行しないような位置におく

table:
  DB 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 8, 9
  DB 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 10, 0, 'A', 'S'
  DB 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0, 0, ']', 'Z', 'X', 'C', 'V'
  DB 'B', 'N', 'M', ',', '.', '/', 0, '*'
     (以下略)
---------------------------------------------------------

・・・ふーむ・・・
これをそのまんまパクるのも、まあありだけど、ちょっとオベンキョしてみよう。

;この時点で、例えばAボタンが押されている。つまり、
;ALには0x1eが入っているとする。
  MOV BH,0 ;BHに0を代入
  MOV BL,AL ;BLに、ALの内容をコピー。
         ;?すると、BXは、0x001e となるのか?

  MOV AL,[BX+table]
;ふむむ・・・ここら辺りがよくわからないなぁ・・・

まあいいや。とりあえず、一旦これを動かしてみよう。

・・・・・あれえぇぇぇぇぇ!?

なんか、メチャクチャな文字が表示されるぞ!? 


4:Re: 続いてキー判定部
hideyosi 10/24 10:37
うーーーん・・・・
どうもおかしいけど、ちょっとだけ解って来たことがある。
この状態だと、たしかにメチャクチャな文字が表示されるが、
一定の法則があるようだ。たとえば、テンキーを123456789
と押すと、OPQKLMGHIを表示する。っということは、キースイッチ
の値とアスキーコードの対応に、一定のズレがあるわけか。

ええと。テンキーのキースイッチ値が・・・

4F,50,51,4B,4C,4D,47,48,49 ;これね。で、アスキーコードが
4F,50,51,4B,4C,4D,47,48,49 ;・・・・あれれ????

なんだこれ? キースイッチの値が直接反映されているだけじゃん!?
そうすると、変換部分にミスがあるのか???

5:Re: 続いてキー判定部
hideyosi 10/24 10:46
あはははははは!!!!!!! ぎょひーーー!!!!

・・・・原因はここでした。

----------------------------------------------------------
;持ってきた値の7ビットだけを抽出
AND AL,0x7F ;二進数 01111111 でANDSする

; ALには0x1e(A)などのキースイッチの値が入る
MOV BH,0
MOV BL,AL
MOV AL,[BX+KEYTABLE] ;この処理で、ALには、文字コードが入っている

JMP MOJIPRINT ;実際に文字を表示する処理
----------------------------------------------------------

MOV BH,0 とかの部分。なんと、MOVとBHの間が、タブではなく、全角スペースでした・・・・・・。つまり、

MOV BH,0
MOV BL,AL
MOV AL,[BX+KEYTABLE]

の部分が、動いてなかったと!!!!!!
うぎゃーー!ハズカスイ・・・・・

えーーーっと!!!! では、気を取り直して・・・・(T∀T)


6:Re: 続いてキー判定部
hideyosi 10/24 11:16
こんな実験をしてみた。

-------------------------------------------
;文字コードとキースイッチコードの対応表
KEYTABLE:
DB '0','1','2','3'

; DB 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 8, 9
; DB 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 10, 0, 'A', 'S'
; DB 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0, 0, ']', 'Z', 'X', 'C', 'V'
; DB 'B', 'N', 'M', ',', '.', '/', 0, '*'
-----------------------------------------------

例の、
MOV BH,0
MOV BL,AL
MOV AL,[BX+KEYTABLE]
の部分の理解。
この状態で、キーを押す。ESCキー。ESCキーのキースイッチ値は、
0x01。で、[BX+KEYTABLE]とかの場合は、KEYTABLEはラベルとなる。
ラベルは、ある特定のアドレスを文字に見立てただけなので、
実際にはアドレスに変換されるはず。(じゃ、仮に0x0200番地だと仮定してみる。)

MOV BH,0
MOV BL,AL

これによって、ESCキーが押された場合には、BXレジスタは、0x0001になる。で、

MOV AL,[BX+KEYTABLE]

とやると、実際には、

MOV AL,[0x0001+0x0200]

というようなことになる。で、実際の0x0201番地っていうのが、

DB '0','1','2','3'

この二番目の要素。すなわち、「1」のアスキーコードになると・・・・
なるほどなるほど!!!! わかってきたぞ!!!!
そうすると、例えば、一覧表をちゃんとした状態で、

MOV AL,[BX+KEYTABLE+1]

なんてイタヅラをすると、全てのキーが一個づつずれるなんてこともできると!あと、
MOV BH,0
MOV BL,AL
これは、そもそもアドレス(オフセット値)を指定するんだから、
16bitが必要なのでこうしているわけね。

??? じゃ、なんでBXレジスタなのか?

これは、「お作法で BX はメモリアドレスの指定に」ということなのかなぁ・・・・

仮にだけど、これをワザとDXレジスタでやってみるとどうなるかな???

・・・・あれれれ! コンパイルエラーになっちゃった。やっぱ、単純にお作法だけじゃなくて、こういう手のアドレス指定は、BXを使うもののようだね。


7:Re: 続いてキー判定部
-- K 10/24 12:06
>??? じゃ、なんでBXレジスタなのか?

 もっともな疑問ですね。

 16bitモードでは、メモリアドレス指定に許させるレジスタの組み合わせが少ししかありません。

 定数
 BX + 定数
 BX + SI + 定数
 BX + DI + 定数
 BP + 定数
 BP + SI + 定数
 BP + DI + 定数
 SI + 定数
 DI + 定数

 それぞれで、定数部分は0であってももちろん構いませんので、[BX]という指定ももちろん可能です。

 今回の目的ではBX、BP、SI、DIのどれでもOKなのですが、その中でBXだけがBLとBHに分けられるので、BXを使ってみました。

 それでは。

8:NASKのバグ??
hideyosi 10/24 12:43
こんなのを見つけた。
-------------------------------------------------------
DB 'A', 'S','D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ''','`', 0, '\'
-------------------------------------------------------

これの後ろから3番目。'A'とかと同じ調子で、’を当てたかったので
こういうふうに書いてみた。まあ、今から考えると、あきらかにおかしな
書き方なんだけど、これがあると、NASKが異常終了してします。

あ、ちなみに、

-------------------------------------------------------
DB 'A', 'S','D', 'F', 'G', 'H', 'J', 'K', 'L', ';', 0x27,'`', 0, '\'
-------------------------------------------------------

これで問題はないんだけのね。(^^;)


9:Re: 続いてキー判定部
hideyosi 10/24 12:57
さーてと。キーコードの変換テーブルは

------------------------------------------------
;文字コードとキースイッチコードの対応表。英字キーボード
KEYTABLE:
; 0 , 01 ,・・・・・
DB 0 , 0 , '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, 9

; 10, 11,・・・・・
DB 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '[', ']', 10, 0

; 1E, 1F,・・・・・
DB 'A', 'S','D', 'F', 'G', 'H', 'J', 'K', 'L', ';', 0x27,'`', 0, '\'

; 2C, 2D,・・・・・
DB 'Z', 'X', 'C', 'V','B', 'N', 'M', ',', '.', '/', 0

; 37 ,38,・・・・
DB '*' , 0,0x20,0,0,0,0,0,0,0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+'

; 4F , 50,・・・・
DB '1' , '2' , '3','0','.'

; 54,55,・・・・
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

; 73,74,・・・・
DB 0,0,0,0,0,0,0,0,0,0,'\'

---------------------------------------------------

とりあえずこれでOKみたいだぞ!?

ほいだば、特殊キーやShiftなんかの処理を追加・・・と。


10:Shiftとか
hideyosi 10/24 20:23
ATのキーボードは、通常は、組み合わせて使うキーは以下だけ。

●Shift
●ALT
●Control

これらのキーは、押せば押され、離せば離される。<なにいってんだろ・・・
考え方としてはこういうことだなぁ。

●あるエリアに、「今押されているか?」を記憶する場所を確保
●押されればそこは1とかになり、離されると0とかになる。
●各キーボードテーブルに、このあるエリアの判定も加える。

えーっと。ShiftやCtrlが押された場合は、ANDして・・・・
ん????

・・・考えてみれば、これらって、全部で6個しかない・・・・

よし!じゃ!

まず、キー状態格納用のエリアを作る

---------------------------------
SSHIFT:
DB 0
SALT:
DB 0
SCTRL:
DB 0
--------------------------------

で、判定部分をこんなふうに改造。

---------------------------------
IINT09:

;押されたキーは何かを調べる
;IN命令で、押されたキーの値を取得
MOV DX,0x60
IN AL,DX

;Shiftの判定。押されているか離されているかはもう
;定数で判定しちゃえ!

;離されている場合。
CMP AL,0x2A
JE SHIFTON

;押されている場合。
CMP AL,0xAA
JE SHIFTOFF

;同じく右側も。
;離されている場合。
CMP AL,0x36
JE SHIFTON

;押されている場合。
CMP AL,0xB6
JE SHIFTOFF

;持ってきた値を一時、AHに複製する
MOV AH,AL
--------------------------------------------

さらに、ジャンプ部分を設置。

--------------------------------------------
SHIFTON:
MOV BX,[SSHIFT]
MOV [BX],0x01

JMP INTEND

SHIFTOFF:
MOV BX,[SSHIFT]
MOV [BX],0x0

JMP INTEND
------------------------------------------

あとは、テーブル判定部分を設置すればOKのはず!

11:Re: Shiftとか
hideyosi 10/24 20:26
・・・・あっれぇぇ?
コンパイルエラーだ!?
どうも、
MOV [BX],0x0
こういうのがまずいらしい。ええっと・・・この場合は・・・


1-

BluesBB ©Sting_Band