我们在学校做一个为期一年的项目。我和一个同事有一个想法,我们应该试着写一个简单的操作系统。我们在Asm和C语言方面没有那么丰富的经验,所以我们认为给自己设定一个任务并尝试解决它是最好的学习方法。
不幸的是,我们已经用键盘输入失败了…
操作系统按预期启动,并写入预期语句"Hello world"在屏幕上。但是只要你按下键盘上的键,屏幕上就会出现一些奇怪的符号。
如果你能解释我们做错了什么,并修复错误,我们将不胜感激
源代码在github上:https://github.com/Fabbboy/alpsos/tree/master/src/impl/kernel/drivers
谢谢你的帮助
EDIT -从github添加代码到stackoverflow
Keyboard.h
#ifndef ALPSOS_KEYBOARD_H
#define ALPSOS_KEYBOARD_H
#include <stdint.h>
uint8_t inb(uint16_t port);
//read from port 0x60
uint8_t keyboard_read_input();
//identify the key pressed
char keyboard_handle_input();
#endif //ALPSOS_KEYBOARD_H
And the keyboardc
#include <stdint.h>
uint8_t inb(uint16_t port){
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
};
//read from port 0x60
uint8_t keyboard_read_input(){
//if something is on port 0x60
while(!(inb(0x64) & 1));
return inb(0x60);
};
//identify the key pressed
char keyboard_handle_input(){
uint8_t input = keyboard_read_input();
if(input == 0x1C){
return 'A';
}
if(input == 0x1D){
return 'B';
}
if(input == 0x1E){
return 'C';
}
if(input == 0x1F){
return 'D';
}
if(input == 0x20){
return 'E';
}
if(input == 0x21){
return 'F';
}
if(input == 0x22){
return 'G';
}
if(input == 0x23){
return 'H';
}
if(input == 0x24){
return 'I';
}
if(input == 0x25){
return 'J';
}
if(input == 0x26){
return 'K';
}
if(input == 0x27){
return 'L';
}
if(input == 0x28){
return 'M';
}
if(input == 0x29){
return 'N';
}
if(input == 0x2A){
return 'O';
}
if(input == 0x2B){
return 'P';
}
if(input == 0x2C){
return 'Q';
}
if(input == 0x2D){
return 'R';
}
if(input == 0x2E){
return 'S';
}
if(input == 0x2F){
return 'T';
}
if(input == 0x30){
return 'U';
}
if(input == 0x31){
return 'V';
}
if(input == 0x32){
return 'W';
}
if(input == 0x33){
return 'X';
}
if(input == 0x34){
return 'Y';
}
if(input == 0x35){
return 'Z';
}
};
你从哪里得到的想法,键盘将返回从0x1C到0x35对应于'A'到'Z'的漂亮的连续范围?
接下来是字母表的键盘扫描码:
a 0x1E
b 0x30
c 0x2E
d 0x20
e 0x12
f 0x21
g 0x22
h 0x23
i 0x17
j 0x24
k 0x25
l 0x26
m 0x27
n 0x31
o 0x18
p 0x19
q 0x10
r 0x13
s 0x1F
t 0x14
u 0x16
v 0x2F
w 0x11
x 0x2d
y 0x15
z 0x2C
这些代码本身并不能告诉你关于字符大小写的任何信息!这是您的程序必须通过查看上按下的caps-lock和/或shift来提供的改进。
如果它是键盘发送的释放代码,则可以设置从端口0x60读取的最高位。大多数情况下,你会想忽略它们。
写一个像样的键盘处理程序不是微不足道的!这比仅仅从端口0x60读取要复杂得多。我相信你可以在网上找到很好的例子。
很可能你的键盘映射是错误的。一个简单的解决方案是制作一个测试版本,其中接收到的原始数字以十六进制显示,允许您创建how键映射。
应该尽可能避免使用if
链,因为它们需要更多的时间和代码空间。使用switch
会更好,但最好使用查找表。您可以将其实现为字符串:
char *keymap = "0123456789ABCDEF";
或作为数组(在我看来可读性更强):
char keymap[NUMBER_KEYS] =
{
[0x00] = ' ',
[0x01] = '1',
/* ... */
[0x1C] = 'A',
[0x1D] = 'B',
[0x1E] = 'C',
[0x1F] = 'D',
[0x20] = 'E',
/* ... */
};
指定初始化器使键代码与其字符之间的关联更易于阅读,但它们不是强制性的。