标签:
转载注明出处:http://www.cnblogs.com/lucasysfeng/p/4847662.html
上一讲地址:http://www.cnblogs.com/lucasysfeng/p/4847662.html
项目地址:https://github.com/lucasysfeng/lucasOS
本讲主要涉及以下三个方面:1. 打印函数封装;2. qemu的使用;3. 项目目录结构调整。 理由如下:1. 后续开发无疑会遇到打印变量的操作,因此有必要封装打印函数(内核开发阶段,无法调用库函数);2. 前两节,我们都是生成镜像文件,然后由VMvare启动,过程较繁琐,后续我们使用qemu虚拟机,可以直接在Linux环境下启动qemu;3. 随着项目的复杂,有必要调整目录结构,并调整Makefile.
本讲没有过多讲解,看代码完全可以理解。本讲只是列出了部分代码,全部代码对应https://github.com/lucasysfeng/lucasOS上的code/chapter3.
0xb8000h是显存开始的地址,因此打印就是操作0xb8000h开始的地址,从0xb8000h这个地址开始,每2个字节表示一个字符,前一个字节是字符的ASCII码,后一个字节是这个字符的颜色和属性。
lib/kprint.c
// 一屏25行 #define LINE_COUNT 25 // 一行80个字符 #define LINE_LENGTH 80 // 字符颜色 #define COLOR 0x04 // 显存开始地址 static unsigned short *display_buf = (unsigned short *) 0xb8000; // 字符属性 static const unsigned short char_attr = COLOR << 8; // 当前光标的坐标 static unsigned char cursor_x = 0; static unsigned char cursor_y = 0; /** * 清屏 */ void print_clear() { unsigned int i; for (i = 0; i < LINE_COUNT * LINE_LENGTH; i++) { display_buf[i] = 0x20 | char_attr; } cursor_x = 0; cursor_y = 0; }
/** * 打印一个字符(为简化逻辑,某些特殊字符均作为换行符处理) */ void print_char(const char c) { if (c >= ‘ ‘) { display_buf[cursor_y * LINE_LENGTH + cursor_x] = c | char_attr; cursor_x++; } else { cursor_x = 0; cursor_y++; } // 每行80个字符,满80个字符换行 if (cursor_x >= 80) { cursor_x = 0; cursor_y++; } scroll(); // 满一屏时,向上滚屏 }
调用打印字符函数。
/** * 打印以\0结尾的字符串 */ void print_str(const char* str) { while (*str) { print_char(*str++); } }
print_dec() print_hex()在github上,此处没给出实现。
#include "kprint.h" int kernel_main() { print_clear(); print_str("hello world, print is OK\n"); print_dec(123); print_char(‘\n‘); print_dec(-123); print_char(‘\n‘); print_hex(11); return 0; }
我们使用qemu启动虚拟机,所以先要安装qemu,qemu的安装和使用此处略。
$ make
$ make qemu
make后会生成kernel内核,并将内核拷贝到lucasOS.img中,运行make qemu就会加载lucasOS.img,并出现下面窗口,表示成功了:
本系列GitHub地址 https://github.com/lucasysfeng/lucasOS,本讲的代码是code/chapter3.
标签:
原文地址:http://www.cnblogs.com/lucasysfeng/p/5036562.html