键盘输入: inc/kbdreg.h, kern/console.c
在kern/console.c中定义了如下数组:
static uint8_t shiftcode[256] =
{
[0x1D] CTL,
[0x2A] SHIFT,
[0x36] SHIFT,
[0x38] ALT,
[0x9D] CTL,
[0xB8] ALT
};
该数组共有(0xB8+1)个元素,几乎所有元素的值均为0, 只有6个元素非空值,分别为:shiftcode[0x1D] = shiftcode[0x9D]= CTL, shiftcode[0x2A] = shiftcode[0x36] = SHIFT, shiftcode[0x38] = shiftcode[0xB8] = ALT.
数组togglecode的定义与shiftcode数组类似。
数组normalmap, shiftmap, ctlmap均用做hash表,用于提高处理速度。
终端显示:
函数cga_init()的作用:
判断cga显示模式为CGA还是MONO,并且设置好addr_6845的值,将指针crt_buf指向图形buffer所在的初始位置,而变量crt_pos则指向cursor所在位置。
在函数cons_intr()的实现中,对于从键盘输入或者串行端口输入的字符,将保存在一个大小为512字节的环行临时缓冲区cons中。 而将缓冲区内容取走的函数为cons_getc().
printf函数族:
snprintf()通过调用vsnprintf()函数实现。 后者将调用函数vprintfmt(), 在该函数中使用sprintputch()将字符输入到printbuf结构类型的变量中。
vprintfmt()函数是printf()函数族实现的核心,它支持左/右对齐,字符0填充, 10/16进制输出等诸多功能。
其实现的switch语句中的default部分比较巧妙:
default:
putch('%', putdat);
for (fmt--; fmt[-1] != '%'; fmt--)
/* do nothing */;
实现原理为"回退". 分析格式化字符串: "hello%2.4KP", 则首先遇到"hello", 直接输出,然后遇到"%", 也直接输出。 接着分析对齐,精度等,然后运行到语句ch = *(unsigned char *) fmt++; ch的值为字符'K',指针fmt指向字符'P'。此时进入default对应部分。 首先fmt--,使得fmt指向字符'K', 分析fmt的前一个位置是否为"%", 不是则继续向前寻找,fmt依次指向字符'4', '.', '2'. 此时由于fmt[-1]为'%', 则退出default语句,继续循环分析。 此时将进入while(1)循环的开始处,将字符原样输出。 即输出依次为"hello", "%", "2.4KP"。
printfmt()中留了一个八进制没有实现。参考十进制和十六进制,可发现该实现其实很简单,只要将如下语句:
// Replace this with your code.
putch('X', putdat);
putch('X', putdat);
putch('X', putdat);
break;
替换为:
putch('0', putdat);
num = getuint(&ap, lflag);
base = 8;
goto number;
即可。
疑惑:
1. 函数lpt_putc()的作用是什么?
2. 在函数cga_putc()的实现中,对应'\t'的处理是输出5个' ', 但是在其monitor下输入'\t'时,光标却会移动到8的整数倍的列的位置, why?
(转贴请注明: by: chunchengfh, from: chunchengfh.cublog.cn)
阅读(1303) | 评论(0) | 转发(0) |