Assembly 如何通过BIOS中断以实模式处理键盘?

Assembly 如何通过BIOS中断以实模式处理键盘?,assembly,operating-system,x86,calculator,bootloader,Assembly,Operating System,X86,Calculator,Bootloader,我必须为我可以运行计算器的操作系统编写代码。它就像桌面计算器一样。为此,我正在阅读我已完成的引导加载程序处于实模式。在此之后,作者将解释保护模式。我不想使用保护模式。我没有时间做那件事。所以我想用bios中断在实模式下编写计算器。可能吗?我认为它可以写在引导加载程序的第二阶段(我不确定)。这意味着我不必使用内核(我不确定)。我不知道如何使用BIOS中断来处理键盘。谁能给我一个链接,这将有助于我在这方面?如果我上面假设的任何错误都是错误的,请纠正我。提前谢谢。您可以处理IRQ 1(通过x86控制器

我必须为我可以运行计算器的操作系统编写代码。它就像桌面计算器一样。为此,我正在阅读我已完成的引导加载程序处于实模式。在此之后,作者将解释保护模式。我不想使用保护模式。我没有时间做那件事。所以我想用bios中断在实模式下编写计算器。可能吗?我认为它可以写在引导加载程序的第二阶段(我不确定)。这意味着我不必使用内核(我不确定)。我不知道如何使用BIOS中断来处理键盘。谁能给我一个链接,这将有助于我在这方面?如果我上面假设的任何错误都是错误的,请纠正我。提前谢谢。

您可以处理IRQ 1(通过x86控制器映射到中断9)并从端口
60h
读取密钥


请参阅。

如果您想使用高级BIOS键盘服务,而不是自己处理键盘中断,那么
INT 16h
就是您想要的


INT 16h
AH=00h
10h
将阻止等待按键(在
AL
中返回ASCII结果);如果要避免阻塞,请使用
AH=01h
11h
查询按键是否首先可用(如果有按键可用,则立即返回
ZF
清除,否则返回设置)。参见例如,或(或谷歌“INT 16h”了解更多信息)。

最小气体引导扇区BIOS示例

当您输入一个字符时,它将被打印到屏幕上

梅因

.code16
.global _start
_start:
cli

/* Set SS and SP as they may get used by BIOS calls. */
xor %ax, %ax
mov %ax, %ss
mov $0x0000, %sp

/* Get input to %al */
mov $0x00, %ah
int $0x16

/* Print the input from %al */
mov $0x0E, %ah
int $0x10

hlt

.org 510
.word 0xaa55
编译并运行:

as -o main.o main.S
ld --oformat binary -o main.img -Ttext 0x7C00 main.o
qemu-system-i386 -hda main.img


在Ubuntu 14.04 AMD64、Binutils 2.24、QEMU 2.0.0和真实硬件Lenovo Thinkpad T400上进行测试。

你会发现[PC中断][1]是一个非常宝贵的工具。您可以在链接上以<4.00美元的价格购买。[1]: -1. 这不是IRQ 9,而是IRQ 1:。IRQ 9可用于通用的其他设备,如PCI设备。IRQ1是键盘中断。@Matt,来自我答案中的链接:
键盘控制器使用IRQ1。x86中断控制器将此映射到中断9,因此从键盘控制器接收IRQ与执行int 9具有相同的效果。
如果PIC未重新映射且您未使用IOAPIC,则与执行中断9相同(与NPX_溢出CPU异常重叠,而不是与IRQ9处理程序重叠)。尽管IRQ和中断之间的映射是可配置的,但IRQ9从不==IRQ1。实际上,从您自己的链接:
键盘控制器使用IRQ1
。由于所有操作系统都将重新映射PIC,因此IRQ不会与CPU异常重叠,因此您最好只说键盘使用IRQ1。@马特,您有一点,IRQ1确实映射到中断9,但没有映射到IRQ1 9。我试图在回答中澄清这一点。感谢您的提醒:)您的代码的潜在问题是假设您有一个有效的堆栈段(SS)和堆栈指针(SP)。BIOS中断需要堆栈空间,因此最好在发出BIOS调用之前设置有效的
SS
SP
。当BIOS跳转到从引导扇区加载的代码时,您不能真正依赖段寄存器的状态。仿真环境和虚拟机环境通常都能使事物保持有效状态,但在某些实际硬件上并非总是如此。@MichaelPetch感谢您提供的信息!我会调查的。我应该把它们设置成什么?对于
SP
,任何高于0x7C00的内存都可以,或者是否有更好更具体的值
SS
我想是0。任何可用的都可以,但我通常远离0x0000:0x1000及以下的内容。您可以将堆栈段放在0x0000:0x7C00(通常是我过去所做的)@MichaelPetch OK!发现这个问题的地方是:对不起,好先生,你知道如何在没有高级bios服务的情况下“自行处理键盘中断”吗?使用这种高级服务的缺点是什么?性能更差吗?