|
80:Re: BEEP hideyosi 10/14 22:27 さて。そんなわけで、私はとりあえずこんなコードを書いてみた。 ------------------------------------ [BITS 16] [OPTIMIZE 1] [OPTION 1] [INSTRSET "8086"] [FORMAT "BIN"] ORG 0x100 ;----------------------------------------------------- ;--- こっから上は、MS-DOSの.COMを作る時の ------------ ;----おまじないだと思ってくれい! ------------ ;----------------------------------------------------- ;-------- 実験部分 ---------------------- ;BIOSのキー入力を乗っ取る MOV AX,0 MOV ES,AX ; ESを0にする。 MOV WORD[ES:0x09*4+0],IINT09 MOV WORD[ES:0x09*4+2],CS MOV AX,DS MOV ES,AX ; ESをもとにもどす。 JMP MAINLLP ;メインループへジャンプ ;メインのループ部分 MAINLLP: JMP MAINLLP ;乗っ取ったキーボード割り込み部分 IINT09: ;押されたキーは何かを調べる ;IN命令で、押されたキーの値を取得 MOV DX,0x60 IN AL,DX ;持ってきた値の7ビットだけを抽出 AND AL,0x7F ;二進数 01111111 でANDSする ;もしその値が1Eだったら、Aボタンが押されている CMP AL,0x1E ;上のCPM命令によってキャリーフラブが変化している。 ;同じならZFが1,CFが0になっている ;もしそうなら、文字表示ルーチンをコールする JE MOJIPRINT ;そうでなかったら、割り込みから戻る IRET ;文字を表示するルーチン MOJIPRINT: MOV AL,0x41 MOV AH,0x0e INT 0x10 IRET ;----------------------------------------------------- ;---- これがないと、暴走しちゃうぞ! ------------- ;----------------------------------------------------- ;MS-DOS終了 INT 0x20 ----------------------------------------- ちなみにこれは、「一部成功一部アカン」でした。 これを実行し、「一回目」のキーボタンがAなら、ちゃんとAを表示していますが、それ以降は無反応になってしまいます。 ・・・っということは、「押されたのがAじゃなかった場合」の処理に問題があるのでしょう。えとえと。こういうのって、どうやってデバッグするのかな? もしかして、DEBUGコマンドを使うのかな??? 81:割り込み処理 -- K 10/14 23:52 おめでとうございます! >これを実行し、「一回目」のキーボタンがAなら、ちゃんとAを表示していますが、それ以降は無反応になってしまいます。 いや、それでよいのです。なぜ無反応になってしまったかというと、割り込み処理が完了したことを、CPUにしか知らせてないからです。 くわしいことは、 http://community.osdev.info/index.php?(PIC)8259A をじっくりと見てください(特に最後の「ものぐさなあなたのために」を見逃さないように)。 82:Re: 割り込み処理 hideyosi 10/16 15:45 ふむ!? Kタンのhttp://community.osdev.info/index.php?(PIC)8259Aをジックリと読んでみた。 ・・・むずかしくてわかりません・・・(T∀T) しかし、そんなぼくらのために(ヲレだけかも)「ものぐさ」というセクションがあった。 ようするにはこういうことらしい。 ●割り込みは、CPUの機能だが、その割り込みの発生・CPUへの発注・関所を行うLSIがあるらしい。 ●このLSIは、キーボードなどから信号が来ると、割り込み信号を作って、CPUに「おい!割り込みがきたぞー!」と知らせ、CPUでは割り込みが発生する。 ●CPU(アセンブラのプログラム部)では、割り込み時に必要な処理は行う。で、その処理が終わったら、IRETで戻ってくる。(つまり、CPUとしては、割り込みは終了している) ●問題は、さっきのLSI。この時点では、まだ、「割り込みがキタゾー!」のまんま。つまり、次の割り込みは待たされている ●つまり、このLSIにも、「CPUとしては、割り込み処理はもう終わったよ。次の割り込みを受け付けていいよ。たのむね」と、教えてあげなくてはいけないらしい。 そのためのコードが、これらしい。 AL = 割り込み番号 + 0x60; OUT(0x20, AL); 83:Re: 割り込み処理 hideyosi 10/16 16:15 うーーーん・・・ AL = 割り込み番号 + 0x60; OUT(0x20, AL); これはどういうことだろう。こういうことなのかな??? ----------------------------------------- [BITS 16] [OPTIMIZE 1] [OPTION 1] [INSTRSET "8086"] [FORMAT "BIN"] ORG 0x100 ;----------------------------------------------------- ;--- こっから上は、MS-DOSの.COMを作る時の ------------ ;----おまじないだと思ってくれい! ------------ ;----------------------------------------------------- ;-------- 実験部分 ---------------------- ;BIOSのキー入力を乗っ取る MOV AX,0 MOV ES,AX ; ESを0にする。 MOV WORD[ES:0x09*4+0],IINT09 MOV WORD[ES:0x09*4+2],CS MOV AX,DS MOV ES,AX ; ESをもとにもどす。 JMP MAINLLP ;メインループへジャンプ ;メインのループ部分 MAINLLP: JMP MAINLLP ;乗っ取ったキーボード割り込み部分 IINT09: ;押されたキーは何かを調べる ;IN命令で、押されたキーの値を取得 MOV DX,0x60 IN AL,DX ;持ってきた値の7ビットだけを抽出 AND AL,0x7F ;二進数 01111111 でANDSする ;もしその値が1Eだったら、Aボタンが押されている CMP AL,0x1E ;上のCPM命令によってキャリーフラブが変化している。 ;同じならZFが1,CFが0になっている ;もしそうなら、文字表示ルーチンをコールする JE MOJIPRINT ;そうでなかったら、割り込みから戻る JMP INTEND ;文字を表示するルーチン MOJIPRINT: MOV AL,0x41 MOV AH,0x0e INT 0x10 JMP INTEND ;割り込み後は、この処理をしないと戻れない INTEND: MOV AL,0x09 ADD AL,0x60 MOV DX,0x20 OUT DX,AL IRET ;----------------------------------------------------- ;---- これがないと、暴走しちゃうぞ! ------------- ;----------------------------------------------------- ;MS-DOS終了 INT 0x20 ----------------------------------------- ・・・ところが、これだとうまくいかないんだよねぇ。なんでだろう???? 84:Re: 割り込み処理 hideyosi 10/16 16:22 っはっはぁぁぁぁ。 なるほどぉ! この場合の「割り込み番号」って、IRQ番号を使うんだぁ! えーっと、キーボードのIRQって・・・・1か! つまり、こうするわけか? ----------------------------------------- [BITS 16] [OPTIMIZE 1] [OPTION 1] [INSTRSET "8086"] [FORMAT "BIN"] ORG 0x100 ;----------------------------------------------------- ;--- こっから上は、MS-DOSの.COMを作る時の ------------ ;----おまじないだと思ってくれい! ------------ ;----------------------------------------------------- ;-------- 実験部分 ---------------------- ;BIOSのキー入力を乗っ取る MOV AX,0 MOV ES,AX ; ESを0にする。 MOV WORD[ES:0x09*4+0],IINT09 MOV WORD[ES:0x09*4+2],CS MOV AX,DS MOV ES,AX ; ESをもとにもどす。 JMP MAINLLP ;メインループへジャンプ ;メインのループ部分 MAINLLP: JMP MAINLLP ;乗っ取ったキーボード割り込み部分 IINT09: ;押されたキーは何かを調べる ;IN命令で、押されたキーの値を取得 MOV DX,0x60 IN AL,DX ;持ってきた値の7ビットだけを抽出 AND AL,0x7F ;二進数 01111111 でANDSする ;もしその値が1Eだったら、Aボタンが押されている CMP AL,0x1E ;上のCPM命令によってキャリーフラブが変化している。 ;同じならZFが1,CFが0になっている ;もしそうなら、文字表示ルーチンをコールする JE MOJIPRINT ;そうでなかったら、割り込みから戻る JMP INTEND ;文字を表示するルーチン MOJIPRINT: MOV AL,0x41 MOV AH,0x0e INT 0x10 JMP INTEND ;割り込み後は、この処理をしないと戻れない INTEND: MOV AL,0x01 ;キーボードの割り込み(IRQ) ADD AL,0x60 ;その番号に、60を足した値 MOV DX,0x20 OUT DX,AL IRET ;----------------------------------------------------- ;---- これがないと、暴走しちゃうぞ! ------------- ;----------------------------------------------------- ;MS-DOS終了 INT 0x20 ----------------------------------------- おぉぉ!!! うまくいったぞ!!!! 逆にKタンの懸念どおり、一回押せば2回Aが出てしまうってのもちゃんと?再現。 よぉぉぉぉし!!!!!!!うまくいったぞ!!! 85:Re: 割り込み処理 hideyosi 10/16 19:16 さてさて。この実験用のショボイコードも、けっこういろいろと できるようになってきた。 これを、とにもかくにもOSっぱく見えるところまで仕上げてみよう。 そのためには、 1、プロンプトを表示してみよう 2、例の、一回押すと二個文字がでる現象をなんとかする 3、キーボードからの文字をちゃんと認識できるようにする 4、一個ぐらい、コマンドを実装したいなぁ(clsとか) そんなわけで、まずは2から手をつけよう。 86:Re: 割り込み処理 hideyosi 10/16 22:04 まず、キーボードからやってくる、「押されたキー信号」は、 0〜6までがキーを示す値。で、最後の7bit目が、「押したのか・離したのか」をあらわします。 今現在、私のコードでは、押して一回、離して一回と割り込みを処理してしまっていますので、一回キーを押すと二回「A」が表示されます。 「キーが離されたときだけ」という反応をすれば、OKなのではと考えました。 今現在はこういうコード。 --------------------------------------------------- IINT09: ;押されたキーは何かを調べる ;IN命令で、押されたキーの値を取得 MOV DX,0x60 IN AL,DX ;持ってきた値の7ビットだけを抽出 AND AL,0x7F ;二進数 01111111 でANDSする ;もしその値が1Eだったら、Aボタンが押されている CMP AL,0x1E ;上のCPM命令によってキャリーフラブが変化している。 ;同じならZFが1,CFが0になっている ;もしそうなら、文字表示ルーチンをコールする JE MOJIPRINT ;そうでなかったら、割り込みから戻る JMP INTEND ----------------------------------------------------- これを、こうしてみたらどうだろ? ------------------------------------------------------ IINT09: ;押されたキーは何かを調べる ;IN命令で、押されたキーの値を取得 MOV DX,0x60 IN AL,DX ;持ってきた値を一時、AHに複製する MOV AH,AL ;AHに複製した値の7ビット目だけを摘出 AND AH,0x80 ;もし、この結果の値が00000000すなわち0x0なら、 ;キーは「押された」となるはず。ここで条件分岐 CMP AH,0x0 ;なにもせずに割り込みを終了する JE INTEND ;違うなら、キーは「離されて」いる。 ;持ってきた値の7ビットだけを抽出 AND AL,0x7F ;二進数 01111111 でANDSする ;もしその値が1Eだったら、Aボタンが押されている CMP AL,0x1E ;上のCPM命令によってキャリーフラブが変化している。 ;同じならZFが1,CFが0になっている ;もしそうなら、文字表示ルーチンをコールする JE MOJIPRINT ;そうでなかったら、割り込みから戻る JMP INTEND --------------------------------------------------------- さて。これでうまくいくかな??? 87:Re: 割り込み処理 hideyosi 10/16 22:09 うはははは! いよーし!! うまくいったぞ!! (^^) 次は、A以外のキーも反応できるようにしょう! 88:Re: 割り込み処理 hideyosi 10/16 23:50 うーーーん・・・・ 押されたキーと、ASCIIのキーコード。なんらかの法則性があるかと思って眺めていたんだけど、まったく関連性がないや・・・ なんらかの計算ルーチンでなんとかなるかと思っていたが、甘かった・・・・ やっぱ、基本的には「絨毯爆撃」で分岐を書くしかないのかなぁ・・・ 89:Re: 割り込み処理 hideyosi 10/18 01:01 いろいろと考えてみたんだけど、やっぱほかにいい方法がみつからないや。もういいや!絨毯爆撃で! ・・・ってなわけで、キーボードの割り込み部分はこういうふうになった。 ------------------------------------------- ;もしその値が1Eだったら、Aボタンが押されている CMP AL,0x1E ;上のCPM命令によってキャリーフラブが変化している。 ;同じならZFが1,CFが0になっている ;もしそうなら、文字表示ルーチンをコールする JE APRINT CMP AL,0x30 ;Bが押されている JE BPRINT CMP AL,0x2E ;Cが押されている JE CPRINT ・ ・ ・ CMP AL,0x15 ;Yが押されている JE YPRINT CMP AL,0x2C ;Zが押されている JE ZPRINT ;そうでなかったら、割り込みから戻る JMP INTEND ;文字ごとにコードをセットする APRINT: MOV AL,0x41 JMP MOJIPRINT BPRINT: MOV AL,0x42 JMP MOJIPRINT ・ ・ ・ YPRINT: MOV AL,0x59 JMP MOJIPRINT ZPRINT: MOV AL,0x5A JMP MOJIPRINT ;文字を表示するルーチン MOJIPRINT: MOV AH,0x0e INT 0x10 JMP INTEND ---------------------------------------------- で、コンパイル。 おぉぉ!!! 文字がいろいろと表示できる!けっこうたのしいぞ!! 今回はとりあえず、ABC・・・XYZまでだけにしておこう。他のキーやShiftとかはちょっと後回し。 ・・・でも、ENTERキーだけは、なんとかそれらしく動作させたいなぁ。 |