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 例程,最好是非阻塞的,但如果谷歌在这方面提供帮助,我会感到很糟糕。一旦我能做到这一点,我就可以从那里做剩下的事情。

我想我在这里要问的是,我在正确的轨道附近吗?通常如何在这个级别上获得键盘输入?

编辑:哦……所以我在保护模式下运行。这当然解释了尝试访问实模式功能时的崩溃。

那么我想我正在寻找如何从保护模式访问键盘 IO。我也许可以自己找到,但如果有人碰巧知道,请随意。再次感谢。

4

7 回答 7

5

您那里的代码正在尝试访问实模式 BIOS 服务。如果您在保护模式下运行,这可能考虑到您正在编写内核,那么中断将不起作用。您将需要执行以下操作之一:

  • 将 CPU 切换到实模式,确保中断向量表正确,并使用您拥有的实模式代码或
  • 编写您自己的保护模式键盘处理程序(即使用输入/输出指令)。

第一个解决方案将涉及运行时性能开销,而第二个解决方案将需要一些有关键盘 IO 的信息。

于 2008-10-20T08:10:07.723 回答
5

如果您使用 gcc 进行编译,除非您使用 linux 内核使用的疯狂的“.code16gcc”技巧(我非常怀疑),否则您不能处于实模式。如果您使用的是 GRUB 多重引导规范,则 GRUB 本身会为您切换到保护模式。因此,正如其他人指出的那样,您将不得不直接与兼容 8042 的键盘/鼠标控制器交谈。除非它是 USB 键盘/鼠标并且 8042 仿真被禁用,否则您将需要一个 USB 堆栈(但您可以使用键盘/鼠标的“启动”协议,这更简单)。

没有人说编写操作系统内核很简单。

于 2008-10-20T10:48:23.473 回答
1

我有一块似乎可以做的 GeekOS

In_Byte(KB_CMD);

进而

In_Byte(KB_DATA);

获取扫描码。我把它放了:keyboard.ckeyboard.hKB_CMD分别KB_DATA为 0x64 和 0x60。我也许还可以指出,这是在 intr:1 的中断处理程序中完成的。

于 2008-10-20T08:07:47.557 回答
1

你做对了,但我似乎记得 djgpp 只生成保护模式输出,你不能从中调用中断。您可以像其他人建议的那样进入实模式,还是更愿意直接解决硬件问题?

于 2008-10-20T14:44:24.370 回答
1

出于解释的目的,假设您自己用汇编语言编写所有内容,包括引导加载程序和内核(*咳*我已经这样做了)。

在实模式下,您可以使用来自 BIOS 的中断例程。您也可以用自己的中断向量替换。但是,所有代码都是 16 位代码,与 32 位代码二进制不兼容。

当您跳过一些难关进入保护模式(包括重新编程中断控制器,以绕过 IBM 在 PC 中使用 Intel 保留中断的事实)时,您有机会设置 16 位和 32 位代码段。这可用于运行 16 位代码。所以你可以用它来访问getchar中断!

... 不完全的。要使此中断起作用,您实际上需要键盘缓冲区中的数据,该数据由不同的 ISR 放置在那里 - 当按键被按下时由键盘触发。有各种问题几乎阻止您在保护模式下将 BIOS ISR 用作实际的硬件 ISR。因此,BIOS 键盘例程是无用的。

另一方面,BIOS 视频通话很好,因为没有硬件触发的组件。您确实必须准备一个 16 位代码段,但如果可以控制,那么您可以通过使用 BIOS 中断来切换视频模式和类似的事情。

回到键盘:您需要(再次假设您正在编写所有代码)是编写键盘驱动程序。除非你是受虐狂(我是其中之一),否则不要去那里。

一个建议:尝试在实模式下编写多任务内核。(那是 16 位模式。)您可以使用所有 BIOS 中断!您没有获得内存保护,但您仍然可以通过挂钩计时器中断来获得先发制人的多任务处理。

于 2008-10-30T08:46:53.613 回答
0

只是一个想法:查看GRUB 的 DOS源代码(asm.s),该console_checkkey功能正在使用 BIOS INT 16H Function 01,而不是功能 00,就像您尝试做的那样。也许您想检查一个键是否正在等待输入。

正如@skizz 建议console_checkkey那样,代码将 CPU 设置为实模式以使用 BIOS 。

您也可以尝试直接使用 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 回答