内核中的屏幕打印模块
这里有三个不一样的入口,在screen.模块中是提供保护模式下在屏幕下打印文本的功能,该模块的具体实现是
如图所示有7个接口须要设计,最重要的一个函数为void PrintChar(char c)-打印字符串的函数,由此总结了以上七个函数接口的关系,以下图所示
如图所示中心函数就为上文所说的函数,由此能够得出上图的关系ide
能够得出最重要的函数为void PrintChar(char c),因此来实现该函数
1.功能定义:在屏幕上打印一个字符
2.实现原理:直接在显存对应的位置写入数据
由上图可知,写入数据的部分能够用四行汇编的语言来实现,可是经过以前的学习,应该是C语言来实现内核开发的,缘由是在屏幕打印字符串使用汇编语言较简单,同时汇编的指令有时是必须由汇编语言来实现,以后在C语言调用。
三.语言中的内嵌汇编-内嵌汇编的语法格式
代码示例
从代码示例能够看到该函数是C语言来编写的,可是经过asm volatile关键字来实现汇编语言的内嵌,在这里须要注意的是由于使用GCC编译器,因此在内嵌汇编时使用的时AT&T汇编格式(与nasm汇编格式不一样)函数
1.首先建立screen.c与screen.h的文件,同时在makefile中进行改动,同时在编译后须要将编译以后的文件保存在后面,因此改代的地方以下
2.screen.h头文件的实现学习
#ifndef SCREEN_H #define SCREEN_H #define SCREEN_WIDTH 80//定义的宽与高-横坐标与纵坐标 #define SCREEN_HEIGHT 25 typedef enum//颜色枚举类型的定义 { SCREEN_GRAY = 0x07, SCREEN_BLUE = 0x09, SCREEN_GREEN = 0x0A, SCREEN_RED = 0x0C, SCREEN_YELLOW = 0x0E, SCREEN_WHITE = 0x0F } PrintColor; //接口的声明 void ClearScreen(); int SetPrintPos(short w, short h); void SetPrintColor(PrintColor c); int PrintChar(char c); int PrintString(const char* s); int PrintIntDec(int n); int PrintIntHex(unsigned int n); #endif
3.screen.c的实现-int SetPrintPos与void SetPrintColor操作系统
static int gPosW = 0; static int gPosH = 0;//全局变量的定义 static char gColor = SCREEN_WHITE; int SetPrintPos(short w, short h) { int ret = 0; if( ret = ((0 <= w) && (w <= SCREEN_WIDTH) && (0 <= h) && (h <= SCREEN_HEIGHT)) ) { unsigned short bx = SCREEN_WIDTH * h + w; gPosW = w; gPosH = h; asm volatile( "movw %0, %%bx\n" "movw $0x03D4, %%dx\n" "movb $0x0E, %%al\n" "outb %%al, %%dx\n" "movw $0x03D5, %%dx\n" "movb %%bh, %%al\n" "outb %%al, %%dx\n" "movw $0x03D4, %%dx\n" "movb $0x0F, %%al\n" "outb %%al, %%dx\n" "movw $0x03D5, %%dx\n" "movb %%bl, %%al\n" "outb %%al, %%dx\n" : : "r"(bx) : "ax", "bx", "dx" ); } return ret; } void SetPrintColor(PrintColor c) { gColor = c; }
4.PrintChar函数的实现设计
int PrintChar(char c) { int ret = 0; if( (c == '\n') || (c == '\r') )//须要注意这两个字符,当出现这俩个时换行,不进行打印 { ret = SetPrintPos(0, gPosH + 1);//从新换行 } else { int pw = gPosW; int ph = gPosH; if( (0 <= pw) && (pw <= SCREEN_WIDTH) && (0 <= ph) && (ph <= SCREEN_HEIGHT) ) { int edi = (SCREEN_WIDTH * ph + pw) * 2;//位置的肯定 char ah = gColor;//颜色的肯定 char al = c;//具体打印的字符 //汇编的嵌入 l四个字节,b为一个字节,w为俩个字节 asm volatile( "movl %0, %%edi\n" "movb %1, %%ah\n" "movb %2, %%al\n" "movw %%ax, %%gs:(%%edi)" "\n" : : "r"(edi), "r"(ah), "r"(al) : "ax", "edi" ); pw++; if( pw == SCREEN_WIDTH ) { pw = 0; ph = ph + 1; } ret = 1; } SetPrintPos(pw, ph); } return ret; }
5.须要将loader.asm进行设置,由于是在32位的保护模式下运行的,选择子也须要改动
6.PrintString的实现
实现方式-循环调用PrintChar直到遇到0结束符
int PrintIntHex的实现
实现方式-将参数n转换为对应的16进制数字字符串,调用PrintString打印转换获得的字符串code