c语言screen函数用法,操作系统-内核中的屏幕打印(上)

操作系统-内核中的屏幕打印(上)

一.屏幕的打印-使用C语言设计一组打印函数,为后续进一步开发内核功能做准备

内核中的屏幕打印模块

882ec5f3d49813178e58b1493c1b5ddf.png

这里有三个不同的入口,在screen.模块中是提供保护模式下在屏幕下打印文本的功能,该模块的具体实现是

3510f10fe746f01a3f350c142d49d8cf.png

如图所示有7个接口需要设计,最重要的一个函数为void PrintChar(char c)-打印字符串的函数,由此总结了以上七个函数接口的关系,如下图所示

9bfd57136d864c71887a6a98585a7d1a.png

如图所示中心函数就为上文所说的函数,由此可以得出上图的关系

二.void PrintChar(char c)函数的实现

可以得出最重要的函数为void PrintChar(char c),所以来实现该函数

1.功能定义:在屏幕上打印一个字符

2.实现原理:直接在显存对应的位置写入数据

4a892959c12b676184f2f1e1788632ef.png

由上图可知,写入数据的部分可以用四行汇编的语言来实现,但是通过之前的学习,应该是C语言来实现内核开发的,原因是在屏幕打印字符串使用汇编语言较简单,同时汇编的指令有时是必须由汇编语言来实现,之后在C语言调用。

三.语言中的内嵌汇编-内嵌汇编的语法格式

55419ce9a8eab40793b1b8947f8bb12b.png

代码示例

e5fee4d655eb42d74721cf14a03fae1f.png

从代码示例可以看到该函数是C语言来编写的,但是通过asm volatile关键字来实现汇编语言的内嵌,在这里需要注意的是因为使用GCC编译器,所以在内嵌汇编时使用的时AT&T汇编格式(与nasm汇编格式不同)

三.屏幕打印的实现

1.首先创建screen.c与screen.h的文件,同时在makefile中进行改动,同时在编译后需要将编译之后的文件保存在后面,所以改代的地方如下

ef507e2fac090504281d404e930a428d.png

2170cc40b3b74aee499e2d6baf4e9feb.png

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位的保护模式下运行的,选择子也需要改动

60c5c3cbf4e6358f52dcb9ab4f3291c3.png

804050c7b3c3d774d19c8071d0132602.png

6.PrintString的实现

实现方式-循环调用PrintChar直到遇到0结束符

int PrintIntHex的实现

实现方式-将参数n转换为对应的16进制数字字符串,调用PrintString打印转换得到的字符串

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值