4

私は、カーネルの最初のビットを一緒にハックしようとしているところです。私は現在、カーネル全体を C コードとしてコンパイルしており、コンソール ウィンドウにテキストを表示することができました。ここで、キーボード入力の受け入れを開始して、実際に使用してプロセス管理を開始できるようにします。

DJGPP を使用してコンパイルし、GRUB をロードしています。また、基本的にコンパイル済みの C コードに直接ジャンプする小さなアセンブリも使用しており、そこから満足しています。

私が行ったすべての調査では、$0x16 の ISR がキーボード バッファーから次の文字を読み取ることを示しているようです。私が知る限り、これは ASCII 値を ah に格納し、キーコードを al に格納するか、その効果を発揮するものです。インライン アセンブリで次のルーチンを使用して、これをコーディングしようとしています。

char getc(void) 
{
    int output = 0;

    //CRAZY VOODOO CODE
    asm("xor %%ah, %%ah\n\t"
        "int $0x16"
        : "=a" (output)
        : "a" (output)
        : 

        );

    return (char)output;
}

このコードが呼び出されると、コアはすぐにクラッシュします。(私は VirtualBox で実行していますが、実際のハードウェアでこの基本的なことを試す必要はないと感じました。)

今、私は実際にいくつかの質問があります。(私のコードは GRUB から起動されたので) 現在、私がリアル モードで実行しているかプロテクト モードで実行しているかは、誰も教えてくれませんでした。プロセス ハンドラをセットアップするまでは、リアル モードで実行する予定でした。

では、リアル モードで実行していると仮定すると、何が間違っているのでしょうか。また、どのように修正すればよいでしょうか。基本的な getc ルーチン、できればノンブロッキングが必要なだけですが、Google がこれを手伝ってくれているとしたら、私はうんざりします。それができたら、そこから残りを行うことができます。

私がここで尋ねているのは、私は正しい道の近くにいるのでしょうか? 一般的に、このレベルでキーボード入力を取得するにはどうすればよいでしょうか?

編集:ああ...私は保護モードで実行しています。これは確かに、リアルモード機能にアクセスしようとしてクラッシュしたことを説明しています.

それで、プロテクトモードからキーボードIOにアクセスする方法を探していると思います。自分で見つけられるかもしれませんが、もしご存知の方がいらっしゃいましたらよろしくお願いします。再度、感謝します。

4

7 に答える 7

5

gccでコンパイルしている場合は、Linuxカーネルが使用するクレイジーな「.code16gcc」トリックを使用していない限り(これは非常に疑わしいです)、リアルモードにすることはできません。GRUBマルチブート仕様を使用している場合、GRUB自体が保護モードに切り替わります。したがって、他の人が指摘しているように、8042互換のキーボード/マウスコントローラに直接話しかける必要があります。USBキーボード/マウスであり、8042エミュレーションが無効になっていない限り、USBスタックが必要になります(ただし、キーボード/マウスには「ブート」プロトコルを使用できます。これはより簡単です)。

OSカーネルの作成が簡単だとは誰も言いませんでした。

于 2008-10-20T10:48:23.473 に答える
5

そこにあるコードは、リアル モードの BIOS サービスにアクセスしようとしています。カーネルを書いていることを考慮して、保護モードで実行している場合、割り込みは機能しません。次のいずれかを行う必要があります。

  • CPU をリアル モードにサンクして、割り込みベクタ テーブルが正しいことを確認し、お手持ちのリアル モード コードを使用するか、
  • 独自のプロテクト モード キーボード ハンドラを記述します (つまり、in/out 命令を使用します)。

最初の解決策には実行時のパフォーマンス オーバーヘッドが含まれますが、2 番目の解決策にはキーボード IO に関する情報が必要になります。

于 2008-10-20T08:10:07.723 に答える
1

説明のために、ブートローダとカーネルのすべてを自分でアセンブリ言語で書いているとしましょう(*咳* 私はこれを実行しました)。

リアル モードでは、BIOS からの割り込みルーチンを利用できます。割り込みベクタを独自のものに置き換えることもできます。ただし、すべてのコードは 16 ビット コードであり、32 ビット コードとバイナリ互換ではありません

プロテクト モードに到達するためにいくつかのハードルを飛び越えた場合 (IBM が PC で Intel 予約割り込みを使用したという事実を回避するために、割り込みコントローラーの再プログラミングを含む)、16 ビットおよび 32 ビットをセットアップする機会があります。コード セグメント。これは、16 ビット コードの実行に使用できます。したがって、これを使用して getchar 割り込みにアクセスできます。

...そうではありません。この割り込みが機能するには、別の ISR (キーが押されたときにキーボードによってトリガーされる ISR) によって配置されたキーボード バッファー内のデータが実際に必要です。プロテクト モードで BIOS ISR を実際のハードウェア ISR として使用することをほとんど妨げるさまざまな問題があります。そのため、BIOS キーボード ルーチンは役に立ちません。

一方、BIOS ビデオ コールは問題ありません。ハードウェア トリガー コンポーネントがないからです。16 ビットのコード セグメントを準備する必要がありますが、それが制御できる場合は、BIOS 割り込みを使用してビデオ モードなどを切り替えることができます。

キーボードに戻る: 必要なのは (ここでもすべてのコードを書いていると仮定して) キーボード ドライバーを作成することです。あなたがマゾヒストでない限り(私はマゾヒストです)、そこには行かないでください。

提案: リアル モードでマルチタスク カーネルを書いてみてください。(これは 16 ビット モードです。) すべての BIOS 割り込みを使用できます。メモリ保護は得られませんが、タイマー割り込みをフックすることで、プリエンプティブなマルチタスクを実現できます。

于 2008-10-30T08:46:53.613 に答える
1

私はGeekOSの一部を持っています

In_Byte(KB_CMD);

その後

In_Byte(KB_DATA);

スキャンコードを取得します。私はそれを上げました: keyboard.ckeyboard.h。それぞれ 0x64 と 0x60 ですKB_CMDKB_DATAこれは、intr:1 の割り込みハンドラーで行われることも指摘できます。

于 2008-10-20T08:07:47.557 に答える
1

あなたは正しいことをしていますが、djgpp は割り込みを呼び出すことができないプロテクト モードの出力のみを生成することを思い出すようです。他の人が提案したように、リアル モードに移行できますか?それとも、ハードウェアに直接対処することをお勧めしますか?

于 2008-10-20T14:44:24.370 に答える
0

単なるアイデア: DOSソース (asm.s) の GRUB を見ると、console_checkkey関数は BIOS を使用してINT 16H Function 01おり、関数 00 を使用していません。キーが入力を待っているかどうかを確認したいかもしれません。

@skizzが提案したように、console_checkkeyコードはBIOSを使用するためにCPUをリアルモードに設定しています。

GRUB 関数を直接使用することもできます (まだリアル モードでマップされている場合)。

アセンブリソースの読み込みに関する注意: このバージョンでは

movb    $0x1, %ah

定数バイト (0x1) をレジスタに移動することを意味します%ah

console_checkkeyGRUB asm.s から:

/*
 * int console_checkkey (void)
 *  if there is a character pending, return it; otherwise return -1
 * BIOS call "INT 16H Function 01H" to check whether a character is pending
 *  Call with   %ah = 0x1
 *  Return:
 *      If key waiting to be input:
 *          %ah = keyboard scan code
 *          %al = ASCII character
 *          Zero flag = clear
 *      else
 *          Zero flag = set
 */
 ENTRY(console_checkkey)
  push  %ebp
  xorl  %edx, %edx

  call  EXT_C(prot_to_real) /* enter real mode */

  .code16

  sti       /* checkkey needs interrupt on */

  movb  $0x1, %ah
  int   $0x16

  DATA32    jz  notpending

  movw  %ax, %dx
  //call    translate_keycode
  call  remap_ascii_char
  DATA32    jmp pending

notpending:
  movl  $0xFFFFFFFF, %edx

pending:
  DATA32    call    EXT_C(real_to_prot)
  .code32

  mov   %edx, %eax

  pop   %ebp
  ret
于 2008-10-20T08:11:47.300 に答える
0

キーボード コントローラをポーリングする例:

Start:
      cli
      mov al,2        ; dissable IRQ 1
      out 21h,al
      sti

;--------------------------------------
; Main-Routine
AGAIN:
      in al,64h       ; get the status
      test al,1       ; check output buffer
      jz short NOKEY
      test al,20h     ; check if it is a PS2Mouse-byte
      jnz short NOKEY
      in al,60h       ; get the key

; insert your code here (maybe for converting into ASCII...)

NOKEY:
      jmp AGAIN
;--------------------------------------
; At the end
      cli
      xor al,al       ; enable IRQ 1
      out 21h,al
      sti
于 2014-05-09T07:39:50.367 に答える