当前位置: 首页 > 编程日记 > 正文

自制操作系统Antz(9)——实现内核 (下) 实现图形化界面

Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html

Linux内核源码分析地址:https://www.cnblogs.com/LexMoon/category/1267413.html

Github项目地址:https://github.com/CasterWx/AntzOS

在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,并且编写了我们自己的内核程序,接下来我们要完成界面的图形化,在显示屏中显示鼠标字符桌面,并显示一个终端界面。

  效果如下:

  现在我们已经简单实现了半终端半桌面的显示,虽然说非常Low,但也是Antz的一大步了。


1.  封装函数

  在前几天我们已经说明了屏幕显示的原理,也就是在显存固定位置写入数据,这对于显卡来说就是像素点。

  如果屏幕显示原理不清楚的可以参考第三天的:http://www.cnblogs.com/LexMoon/p/antz03.html

  为了方便实现图像化,我将显卡写入的代码使用C语言封装成了函数,颜色定义为数组。

 1     static unsigned char table_rgb[16 * 3] = {2         0x00, 0x00, 0x00,    /*  0:黑 */3         0xff, 0x00, 0x00,    /*  1:梁红 */4       ....5         0x84, 0x00, 0x84,    /* 13:暗紫 */6         0x00, 0x84, 0x84,    /* 14:浅暗蓝 */7         0x84, 0x84, 0x84    /* 15:暗灰 */8     };
View Code

  这个数组对应了我们要显示的颜色RGB值,将数组下标定义对应的枚举值,可以更加方便使用。

  要在显示器显示字体,可以使用putfont8_asc ()函数,它调用了putfont8()函数:   

 1 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)2 {3     extern char hankaku[4096];4     /* C语言中,字符串都是以0x00结尾 */5     for (; *s != 0x00; s++) {6         putfont8(vram, xsize, x, y, c, hankaku + *s * 16);7         x += 8;8     }9     return;
10 }
View Code

  鼠标指针实现是将其呈图形化的写入,函数init_mouse_cursor8():

 1 void init_mouse_cursor8(char *mouse, char bc)2 3 {4     static char cursor[16][16] = {5      6     };7     int x, y;8 9     for (y = 0; y < 16; y++) {
10         for (x = 0; x < 16; x++) {
11             if (cursor[y][x] == '*') {
12                 mouse[y * 16 + x] = COL8_000000;
13             }
14             if (cursor[y][x] == 'O') {
15                 mouse[y * 16 + x] = COL8_FFFFFF;
16             }
17             if (cursor[y][x] == '.') {
18                 mouse[y * 16 + x] = bc;
19             }
20         }
21     }
22     return;
23 }
View Code


2 . GDT与lDT

  GDT是在32位时16位寻址模式的改造,在学习汇编时,我们所说的 段:偏移量(段x16+偏移量)寻址方式已经不能使用了,所以厂商们使用了GDT,在不改变段寄存器位数的情况下,完成了32位段寻址,就是利用GDT。

(1)全局描述符表GDT(Global Descriptor Table)

  在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。

  基地址指定GDT表中字节0在线性地址空间中的地址,表长度指明GDT表的字节长度值。指令LGDT和SGDT分别用于加载和保存GDTR寄存器的内容。在机器刚加电或处理器复位后,基地址被默认地设置为0,而长度值被设置成0xFFFF。在保护模式初始化过程中必须给GDTR加载一个新值。

(2)段选择子(Selector)

  由GDTR访问全局描述符表是通过“段选择子”(实模式下的段寄存器)来完成的。段选择子是一个16位的寄存器(同实模式下的段寄存器相同)

  段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。他的index(描述符索引)部分表示所需要的段的描述符在描述符表的位置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符。然后用描述符表中的段基址加上逻辑地址(SEL:OFFSET)的OFFSET就可以转换成线性地址,段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。

  关于特权级的说明:任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。

  例如给出逻辑地址:21h:12345678h转换为线性地址

  a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;左后的01b代表特权级RPL=1

  b. OFFSET=12345678h若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h

(3)局部描述符表LDT(Local Descriptor Table)

  局部描述符表可以有若干张,每个任务可以有一张。我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。

    

  关于GDT于IDT初始化的代码,它们可以实现鼠标的移动,现在我还没有去写它,此次的任务只是显示。

  最新的Antz系统镜像和代码已经上传到我的github了,这里只列举出剩余的主要代码。

#include <stdio.h>
struct BOOTINFO {char cyls, leds, vmode, reserve;short scrnx, scrny;char *vram;
};struct SEGMENT_DESCRIPTOR {short limit_low, base_low; char base_mid, access_right; char limit_high, base_high; }; struct GATE_DESCRIPTOR { short offset_low, selector; char dw_count, access_right; short offset_high; }; void init_gdtidt(void); void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar); void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar); void load_gdtr(int limit, int addr); void load_idtr(int limit, int addr); void HariMain(void) { struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; char s[40], mcursor[256]; int mx, my; init_palette(); init_screen(binfo->vram, binfo->scrnx, binfo->scrny); mx = (binfo->scrnx - 16) / 2; /* 计算画面的中心坐标*/ my = (binfo->scrny - 28 - 16) / 2; init_mouse_cursor8(mcursor, COL8_00FFFF); putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx+20, my, mcursor, 16); for (;;) { io_hlt(); } } void set_palette(int start, int end, unsigned char *rgb) { int i, eflags; eflags = io_load_eflags(); /* 记录中断许可标志的值 */ io_cli(); /* 将中断许可标志置为0,禁止中断 */ io_out8(0x03c8, start); for (i = start; i <= end; i++) { io_out8(0x03c9, rgb[0] / 4); io_out8(0x03c9, rgb[1] / 4); io_out8(0x03c9, rgb[2] / 4); rgb += 3; } io_store_eflags(eflags); /* 复原中断许可标志 */ return; } void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1) { int x, y; for (y = y0; y <= y1; y++) { for (x = x0; x <= x1; x++) vram[y * xsize + x] = c; } return; } void init_screen(char *vram, int x, int y) { boxfill8(vram, x, COL8_00FFFF, 0, 0, x, y); boxfill8(vram, x, COL8_C6C6C6, 0, 0, x/2, y); boxfill8(vram, x, COL8_000000, 3, 15, x/2-3, y-3); boxfill8(vram, x, COL8_008400, 165 , 30, 215, 40); boxfill8(vram, x, COL8_008400, 265 , 30, 315, 40); boxfill8(vram, x, COL8_008400, 190 , 60, 200, 70); boxfill8(vram, x, COL8_008400, 280 , 60, 290, 70); boxfill8(vram, x, COL8_008400, 235 , 65, 245, 100); boxfill8(vram, x, COL8_008400, 235-15 , 65+40, 245-15, 85+30); boxfill8(vram, x, COL8_008400, 235 , 65+40, 245, 85+30); boxfill8(vram, x, COL8_008400, 235+15 , 65+40, 245+15, 85+30); boxfill8(vram, x, COL8_008400, 200 , 130, 280, 140); boxfill8(vram, x, COL8_008400, 200 , 130, 210, 160); boxfill8(vram, x, COL8_008400, 270 , 130, 280, 160); boxfill8(vram, x, COL8_008400, 200 , 150, 280, 160); return; } void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; char *p, d /* data */; for (i = 0; i < 16; i++) { p = vram + (y + i) * xsize + x; d = font[i]; if ((d & 0x80) != 0) { p[0] = c; } if ((d & 0x40) != 0) { p[1] = c; } if ((d & 0x10) != 0) { p[3] = c; } if ((d & 0x20) != 0) { p[2] = c; } if ((d & 0x08) != 0) { p[4] = c; } if ((d & 0x04) != 0) { p[5] = c; } if ((d & 0x02) != 0) { p[6] = c; } if ((d & 0x01) != 0) { p[7] = c; } } return; } void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s) { extern char hankaku[4096]; /* C语言中,字符串都是以0x00结尾 */ for (; *s != 0x00; s++) { putfont8(vram, xsize, x, y, c, hankaku + *s * 16); x += 8; } return; } void init_mouse_cursor8(char *mouse, char bc) /* マウスカーソルを準備(16x16) */ { static char cursor[16][16] = {     //鼠标图形 }; int x, y; for (y = 0; y < 16; y++) { for (x = 0; x < 16; x++) { if (cursor[y][x] == '*') { mouse[y * 16 + x] = COL8_000000; } if (cursor[y][x] == 'O') { mouse[y * 16 + x] = COL8_FFFFFF; } if (cursor[y][x] == '.') { mouse[y * 16 + x] = bc; } } } return; } void putblock8_8(char *vram, int vxsize, int pxsize, int pysize, int px0, int py0, char *buf, int bxsize) { int x, y; for (y = 0; y < pysize; y++) { for (x = 0; x < pxsize; x++) { vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x]; } } return; }

转载于:https://www.cnblogs.com/LexMoon/p/antz09.html

相关文章:

python迷宫万花筒代码_利用广度优先遍历搜索迷宫的python源代码

广度优先遍历简称为DFS&#xff0c;是数据结构中比较常用的一个算法&#xff0c;主要原理是采用队列先进先出的规则&#xff0c;一层一层的访问图的节点。而迷宫问题接近与遍历&#xff0c;但是不同于遍历&#xff0c;主要考虑是采用栈的形式标记路径&#xff0c;并对当前节点和…

联想拯救者Y9000-ubuntu-nvidia-驱动安装

概述 由于联想拯救者Y9000的硬件都比较新&#xff0c;所以在安装ubuntu 的时候会有很多驱动的问题&#xff0c;本文主要讲解安装nvidia驱动的问题&#xff0c;如网卡、触摸板无效的其他问题请在我的其他文章中查找 友情提示 安装完系统之后先插网线装ssh服务&#xff0c; 确…

修改远程桌面端口

修改远程桌面端口需要两个步骤&#xff1a;  1、打开注册表 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp]&#xff0c;修改右边PortNamber的值&#xff0c;其默认值是3389&#xff0c;修改成所希望的端口即可&#xff0c;例如3…

开发管理 CheckLists(4) -风险管理

本文章主要介绍在项目启动前怎么样分步骤的去识别风险,才去什么方式去识别风险. 有需要做风险识别的朋友可以按照下面的步骤简单的走上一遍,或者可以提高项目的成功率 注意&#xff1a;本文章只是你做风险识别的chekcLists ,上面提到的一些分析方法都只是简单的介绍…

python的深拷贝与浅拷贝

对于list, set, dict来说, 直接赋值. 其实是把内存地址交给变量. 并不是复制⼀份内容. 两个变量的内容其实为一个地址,如果要在复制的同时分配新的地址则需要用到深拷贝和浅拷贝的命令 lst1 ["何炅", "杜海涛","周渝⺠", ["麻花藤", …

safari post 请求接收不到_我是谁?我在哪?我要到哪去?——HTTP请求头

各位小白帽们好又到了新一期的知识点咯在正片开始之前再次提醒一下各位因为联盟管理的需要本周五(12月4日)5点半将会对各位在平台的答题分数进行统计筛选部分排名靠前的童鞋作为核心的正式会员考核压力来了大家是不是有点紧张呢只要积极学习知识积极参与答题向本AI卖萌要flag相…

SharePoint 2013 配置开发环境,需安装VS2012插件

SharePoint 2013已经安装好了&#xff0c;接下来就是配置开发环境&#xff0c;安装VS2012&#xff0c;但是&#xff0c;装好了以后&#xff0c;发现没有SharePoint 2013开发的支持&#xff0c;如下图&#xff1a; 然后&#xff0c;去网上查找资料&#xff0c;VS2012对SharePoin…

联想拯救者Y9000-ubuntu-U盘启动失败解决方法

注意事项 1、U盘要是USB3.0的U盘&#xff0c;否则基本会失败 安装到最后的时候报一个 cd/dvd 设备 low speed的故障 2、bios 设置 硬盘模式 选择 AHCImode 模式&#xff0c; 否则刷机不成功 3、 U盘镜像的烧录方式&#xff0c; 实测windows 下的rufus工具有效

RedHat Enterprise 5.1下OpenLDAP的配置及PAMNSS的配置

服务器端 192.1.0.160 客户机端 192.1.0.221 一、在服务器端配置LDAP服务&#xff1a; 1.下载 openldap-2.4.11.tar.gz和db-4.7.25.tar.gz 2.安装BerkeleyDB #rpm -qa|grep db # tar xvf db-4.7.25.tar.gz # cd db_4.7.25# cd build_unix/# ../dist/configure -prefix/usr/loca…

pwn with glibc heap(堆利用手册)

前言 ​ 对一些有趣的堆相关的漏洞的利用做一个记录&#xff0c;如有差错&#xff0c;请见谅。 ​ 文中未做说明 均是指 glibc 2.23 ​ 相关引用已在文中进行了标注&#xff0c;如有遗漏&#xff0c;请提醒。 简单源码分析 ​ 本节只是简单跟读了一下 malloc 和 free 的源码&am…

COCO KeyPoints关键点数据集准备

COCO KeyPoints关键点数据集准备 概述 网上搜了一圈&#xff0c;coco关键点数据集准备的内容比较少&#xff0c;这里写一篇完成的标注流程到数据集准备的文章&#xff0c;以备后忘 标注工具 coco官方标注工具: coco–annotator https://github.com/jsbroks/coco-annotator …

Boost 1.53.0 发布,可移植的C++标准库

Boost 1.53.0 发布了&#xff0c;包含了 5 个新的库&#xff0c;修复了一些安全漏洞以及 Boost.Locale 组件的 bug 。 新增的 5 个库包括&#xff1a; Boost.AtomicBoost.CoroutineBoost.MultiprecisionBoost.Numeric.OdeintBoost.Lockfree完整改进记录说明请看 changelog 下载…

华为云客户端_从技术角度解读华为云手机之于普通用户的可行性

9月1日&#xff0c;华为云宣布&#xff0c;华为首创全球首个ARM芯片的“云手机”正式公测。此消息一出&#xff0c;普通消费市场一片赞美之声&#xff0c;想必大家更多的想法是终于让华为找到了一个应对当前手机困局的解决方案了。据悉&#xff0c;华为云鲲鹏手机早在今年3月就…

c#获取应用程序目录

string str1 Process.GetCurrentProcess().MainModule.FileName;//可获得当前执行的exe的文件名。 string str2Environment.CurrentDirectory;//获取和设置当前目录&#xff08;即该进程从中启动的目录&#xff09;的完全限定路径。//备注 按照定义&#xff0c;如果该进程在本…

【BZOJ5311/CF321E】贞鱼/Ciel and Gondolas(动态规划,凸优化,决策单调性)

【BZOJ5311/CF321E】贞鱼/Ciel and Gondolas&#xff08;动态规划&#xff0c;凸优化&#xff0c;决策单调性&#xff09; 题面 BZOJCF洛谷 辣鸡BZOJ卡常数&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 辣鸡BZOJ卡常数&#xff01;&#xff01;&…

python定时任务contrib_django+celery配置(定时任务+循环任务)

下面介绍一下djangocelery的配置做定时任务1.首先介绍一下环境和版本python2.7django 1.8.1celery 3.1.23django-celery 3.1.172.celery的安装sudo pip install celery3.1.23sudo pip install django-celery3.1.173.新建一个项目(1)django-admin startproject django_celery…

CenterNet KeyPoints 关键点训练自己的数据

概述 网上搜了一圈&#xff0c;关于CenterNet 训练关键点数据的资料非常少&#xff0c;而且讲得都很模糊&#xff0c;没法解决实际问题&#xff0c;也未说明细节和要素。在踏坑许久之后&#xff0c;才跑通CenterNet的关键点训练&#xff0c;于是记录一下踏坑历程&#xff0c;以…

Java学习笔记---字符类型

一、字符类型也算是整数类型的一种 字符类型在内存中占有2个字节&#xff0c;可以用来保存英文字母等字符。计算机处理字符类型时&#xff0c;是把这些字符当成不同的整数来看待&#xff0c;因此&#xff0c;严格说来&#xff0c;字符类型也算是整数类型的一种&#xff08;小写…

我的家庭私有云计划-16

嗯&#xff0c;上午测试S2S的稳定性&#xff0c;改掉几个bug。还挺忙的。这会儿让机器跑测试去&#xff0c;腾出点时间&#xff0c;我们接着聊。 呵呵&#xff0c;昨天哪&#xff0c;已经有朋友批评我了&#xff0c;说我有点贪大求全&#xff0c;这个论坛什么的没必要自己实现&…

“cyl projection cannot cross pole” 解决方法

解决方法&#xff1a; 1、尝试更新NumPy以及相关模块&#xff1a; 在CMD里面执行 conda update –all 遇到提示选择yes/y 更新完毕后看是否可以载入。 发现并不能成功更新&#xff0c;于是采取了下面方法&#xff1a; 2、如果方法一不能解决&#xff0c;那么尝试卸载相关库&…

使用ubuntu(18.04) 作为软路由器连接互联网

使用ubuntu&#xff08;18.04&#xff09; 作为软路由器连接互联网 背景: 最近要用ubuntu机器作为中继路由&#xff0c;需要配置一下&#xff0c;但是内网外网网上找了一圈&#xff0c;五花八门的&#xff0c;照着做没有一个靠谱的&#xff0c;遇到的问题也没有任何说明&#…

程序员肿么了?为何总被认为是“屌丝”

没有想到会这么多人&#xff0c;有一点我强调一下&#xff0c;我的标题是被认为&#xff0c;而不是说真是。其实程序员相比其他行业不见得差&#xff0c;只是社会整体认可度不高。&#xff08;或者说认知&#xff09; 本文纯属闲时娱乐&#xff0c;请勿当真&#xff0c;请勿较真…

python空值填充_pandas | DataFrame基础运算以及空值填充

今天是pandas数据处理专题的第四篇文章&#xff0c;我们一起来聊聊DataFrame的基本运算。上一篇文章当中我们介绍了DataFrame数据结构当中一些常用的索引的使用方法&#xff0c;比如iloc、loc以及逻辑索引等等。今天的文章我们来看看DataFrame的一些基本运算。数据对齐我们可以…

Python学习之路基础篇--10Python基础,函数进阶

1 命名空间 对于Python 来说命名空间一共有三种 1 内置命名空间 —— Python 解释器 就是Python 解释器一启动就可以使用的名字&#xff0c;储存在内置命名空间中。内置的名字在启动解释器的时候被加载进内存里 2 全局命名空间 —— 我们所命名的&#xff0c;但不是函数中的代码…

C语言中整型浮点型在计算机中的存储

第一次写博客&#xff0c;遣词造句有点菜&#xff0c;算是一次简单梳理&#xff0c;慢慢学习人家的博客风格&#xff0c;随着学习的深入再做修改。 本次学习的是C语言在VS下的编译调试&#xff0c;对于初学者两说&#xff0c;首先说一下如何监控变量&#xff0c;以及监控变量在…

判断交换机性能好坏的九个因素

【文章摘要】把握千兆交换机的主要性能指标是关键&#xff0c;而判断交换机性能的好坏&#xff0c;需要从以下几方面的因素出发... 把握千兆交换机的主要性能指标是关键&#xff0c;而判断交换机性能的好坏&#xff0c;需要从以下几方面的因素出发&#xff1a;   转发技术  …

xgboost回归预测模型_偏最小二乘回归分析法 从预测角度对所建立的回归模型进行比较...

在实际问题中&#xff0c;经常遇到需要研究两组多重相关变量间的相互依赖关系&#xff0c;并研究用一组变量(常称为自变量或预测变量)去预测另一组变量(常称为因变量或响应变量)&#xff0c; 除了最小二乘准则下的经典多元线性回归分析(MLR)&#xff0c;提取自变量组主成分的主…

win7的IE缓存,临时文件,cookies和历史记录

2019独角兽企业重金招聘Python工程师标准>>> vista、win7的缓存以及临时文件、Cookies和历史记录都在以下几个地方&#xff1a; 缓存: %userprofile%\AppData\Local\Microsoft\Windows\Temporary Internet Files Temp: %userprofile%\AppData\Local\Temp Cookies: %…

Sql Server函数全解(四)日期和时间函数

阅读目录 1.获取系统当前日期的函数getDate();2.返回UTC日期的函数UTCDATE()3.获取天数的函数DAY(d)4.获取月份的函数MONTH(d)5.获取年份的函数YEAR(d)6.获取日期中指定部分字符串值的函数DATENAME(dp,d)7.获取日期中指定部分的整数值的函数DATEPART(dp,d)8.计算日期和时间的函…

关于python的比赛_【蓝桥杯】——python集团的比赛技巧,Python,组

【蓝桥杯】—— Python组比赛技巧蓝桥杯是大学生IT学科赛事&#xff0c;由工业和信息化部人才交流中心主办&#xff0c;所以对于大学生还说还是非常值得去参加的&#xff0c;2020年第十一届蓝桥杯新增了大学Python组&#xff0c;不分组别&#xff0c;第一届没有历届的真题&…