如果跟着我学到现在,一定知道到哪里去下载代码,算了,地址在这https://github.com/cfenollosa/os-tutorial/tree/master/15-video-ports,这个地址里有这节课要用到的代码,如果之前你只是看看就算了,这节课就是不上手就再也跟不上的关键节点。代码中有一点点问题,Makefile中在qemu 调用-s时加一个-S(比如这样 -sS),这样gdb才能够真正控制qemu的运行。
看到代码了吗?如果还没打开代码,本课程将不再欢迎你。
drive
文件夹中有两个c程序,用到了Inline Assembly的写法,这是一个难点,这段代码这么写就显得更加难理解。
原本的Inline Assembly的用法是这样:
int a=10, b;
asm ("movl %1, %%eax;
movl %%eax, %0;"
:"=r"(b) /* 输出 */
:"r"(a) /* 输入 */
:"%eax" /* 用到的寄存器 */
);
我们的代码是这样
__asm__("in %%dx, %%al"
: "=a" (result)
: "d" (port));
"in %%dx, %%al"就是汇编指令
"=a" (result) 是指将eax寄存器的值写入c语言中的变量result
中。
"d" (port)) 是指将port变量的值写到edx中。
绕不绕?感觉绕就正常了,因为你不知道in %%dx, %%al
是在干什么,让我们看看kernel/kernel.c中如何调用这段代码的。
port_byte_out(0x3d4, 14); /* 14是请求高位字节,0x3d4是一个地址,用于与显卡交互 */
/* 索取的数据将出现在 (0x3d5)中 */
int position = port_byte_in(0x3d5);
position = position << 8; /* high byte */
port_byte_out(0x3d4, 15); /* 请求低位字节 */
position += port_byte_in(0x3d5);
其实它是在请求显卡告诉咱们,现在光标在什么位置,光标的位置是一个16位的数据,分两个字节提取,提取流程是:
1.在0x3d4位置写入14,光标位置高字节信息出现在0x3d5中
2.在0x3d4位置写入15,光标位置低字节信息结果出现在0x3d5中。
由此,实现了一个显示数据的接口,以后再要打印什么ASCII码就方便多了。