首先就是对前一天程序的一些优化,引入了结构体:

struct BOOTINFO {char cyls, leds, vmode, reserve;short scrnx, scrny;char *vram;
};void HariMain(void)
{char *vram;int xsize, ysize;struct BOOTINFO *binfo;init_palette();binfo = (struct BOOTINFO *) 0x0ff0;xsize = (*binfo).scrnx;ysize = (*binfo).scrny;vram = (*binfo).vram;init_screen(vram, xsize, ysize);for (;;) {io_hlt();}
}

这里面用到的结构体BOOTINFO其实只是一个存储单元。

binfo = (struct BOOTINFO *) 0x0ff0;这句获取0x0ff0开始一连串值。

作用相当于binfo_scrnx = (short *)0xff4;等几句。

另外,作为参数时,可以不用传入那么多参数。

之后就是,字符显示:

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 & 0x20) != 0) { p[2] = c; }if ((d & 0x10) != 0) { p[3] = 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;
}

这段代码显示字符A,具体原理就是用for语句将8个像素的程序循环16遍。需要在HariMain里,

初始化

static char font_A[16] = {

0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,

0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00

};

作为参数。

一个A就出现这么多代码,肯定不行。所以作者引入了OSASK字体。加入hankaku.txt文件。另需编译器makefont.exe将之编译为hankaku.bin文件。

新的Makefile:

TOOLPATH = ../z_tools/
INCPATH  = ../z_tools/haribote/MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
NASM     = $(TOOLPATH)nasm.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = deldefault :$(MAKE) imgipl.bin : ipl.asm Makefile$(NASM) ipl.asm -o ipl.binmain.bin : main.nas Makefile$(NASK) main.nas main.bin main.lstc_main.gas : c_main.c Makefile$(CC1) -o c_main.gas c_main.cc_main.nas : c_main.gas Makefile$(GAS2NASK) c_main.gas c_main.nasc_main.obj : c_main.nas Makefile$(NASK) c_main.nas c_main.obj c_main.lstassemblyFunc.obj : assemblyFunc.nas Makefile$(NASK) assemblyFunc.nas assemblyFunc.obj assemblyFunc.lsthankaku.bin : hankaku.txt Makefile$(MAKEFONT) hankaku.txt hankaku.binhankaku.obj : hankaku.bin Makefile$(BIN2OBJ) hankaku.bin hankaku.obj _hankakuc_main.bim : c_main.obj assemblyFunc.obj hankaku.obj Makefile$(OBJ2BIM) @$(RULEFILE) out:c_main.bim stack:3136k map:c_main.map \c_main.obj assemblyFunc.obj hankaku.obj
# 3MB+64KB=3136KBc_main.hrb : c_main.bim Makefile$(BIM2HRB) c_main.bim c_main.hrb 0haribote.sys : main.bin c_main.hrb Makefilecopy /B main.bin+c_main.hrb haribote.sysharibote.img : ipl.bin haribote.sys Makefile$(EDIMG)   imgin:../z_tools/fdimg0at.tek \wbinimg src:ipl.bin len:512 from:0 to:0 \copy from:haribote.sys to:@: \imgout:haribote.imgimg :$(MAKE) haribote.imgrun :$(MAKE) img$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin$(MAKE) -C ../z_tools/qemuinstall :$(MAKE) img$(IMGTOL) w a: haribote.imgclean :-$(DEL) *.bin-$(DEL) *.lst-$(DEL) *.gas-$(DEL) *.obj-$(DEL) c_main.nas-$(DEL) c_main.map-$(DEL) c_main.bim-$(DEL) c_main.hrb-$(DEL) haribote.syssrc_only :$(MAKE) clean-$(DEL) haribote.img

之后有了显示字符和字符串的函数:

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 & 0x20) != 0) { p[2] = c; }if ((d & 0x10) != 0) { p[3] = 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];for (; *s != 0x00; s++) {putfont8(vram, xsize, x, y, c, hankaku + *s * 16);x += 8;}return;
}

鼠标的显示就是一样的道理了:

void init_mouse_cursor8(char *mouse, char bc)
/* 准备鼠标指针 */
{static char cursor[16][16] = {"**************..","*OOOOOOOOOOO*...","*OOOOOOOOOO*....","*OOOOOOOOO*.....","*OOOOOOOO*......","*OOOOOOO*.......","*OOOOOOO*.......","*OOOOOOOO*......","*OOOO**OOO*.....","*OOO*..*OOO*....","*OO*....*OOO*...","*O*......*OOO*..","**........*OOO*.","*..........*OOO*","............*OO*",".............***"};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;
}

此时c_main.c里main函数如下:

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_008484);putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);sprintf(s, "(%d, %d)", mx, my);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);for (;;){io_hlt();}
}

可见,先初始化调色板、再初始化屏幕、再初始化鼠标,然后画鼠标,显示字符。

这章涉及保护模式寻址,关于GDT。

2016.06.06我已经非常透彻理解了保护模式寻址,画了下面的图:

虽然人们在谈到中断(Interrupt)时,总会拿轮询(Polling)来做“反面”例子,但中断和轮询并不是完全对立的两个概念,呃,它们是对立统一的。
“CPU执行完每条指令时,都会去检查一个中断标志位”,这句话是所有关于中断长篇大论的开场白,但很容易被人忽略,其实,这就是中断的本质。
举个例子,CPU老板是一家公司的光杆司令,所有的顾客都要他亲自跑去处理,还要跟有关部门打点关系,CPU觉得顾客和公关这两样事它一个人搞不来,这就是轮询;终于这家公司升级发展了,CPU老板请了一个秘书,所有的顾客都先由秘书经手,CPU心情好的时候就去看一下,大部分时间都忙着去公关了,这时它觉得轻松了很多,这就是中断了~~
也就是说,中断和轮询是从CPU老板的角度来看的,不管怎样,事件都还是有人来时刻跟踪才能被捕获处理,不过是老板还是秘书的问题。所有的中断(或者异步,回调等)背后都有一个轮询(循环,listener)。
通往32位之路:
PIC关闭一切中断                     
; PIC关闭一切中断
;    根据AT兼容机的规格、初始化PIC
;    必须在CLI之前进行,到CLI挂起
;    随后进行PIC初始化MOV        AL,0xffOUT        0x21,ALNOP                        ; 如果连续进行OUT命令,有些机种不可以OUT        0xa1,ALCLI                        ; 禁止CPU级别中断

设置A20

; OPEN A20GATECALL    waitkbdoutMOV        AL,0xd1OUT        0x64,ALCALL    waitkbdoutMOV        AL,0xdf            ; enable A20OUT        0x60,ALCALL    waitkbdout

切换到保护模式。

INSTRSET指令,是为了能够使用386以后的LGDT,EAX,CR0等关键字。

通过带入CR0而切换到保护模式时,要马上执行JMP指令。因为变成保护模式后,机器语言的解释要发生变化。CPU为了加快指令的执行速度而使用了管道这一机制,就是说,前一条指令还在执行的时候,就开始解释下一条甚至是再下一条指令。因为模式变了,就得重新解释一遍,所以加入了JMP指令

; 保护模式

[INSTRSET "i486p"]                ; 开始使用486命令LGDT    [GDTR0]            ; 临时GDTMOV        EAX,CR0AND        EAX,0x7fffffff    ; bit31设0,禁止分页OR        EAX,0x00000001    ; bit0设1,为了切换到保护模式MOV        CR0,EAXJMP        pipelineflush
pipelineflush:MOV        AX,1*8            ;  可读写的段,32bitMOV        DS,AXMOV        ES,AXMOV        FS,AXMOV        GS,AXMOV        SS,AX

转载于:https://www.cnblogs.com/rixiang/p/5419129.html

自制操作系统(五) 保护模式寻址原理、字符鼠标指针显示相关推荐

  1. 操作系统——认识保护模式

    操作系统--认识保护模式 实验目的及内容 认真阅读章节资料,掌握什么是保护模式,弄清关键数据结构:GDT.descriptor.selector.GDTR, 及其之间关系,阅读pm.inc文件中数据结 ...

  2. 操作系统——让操作系统走进保护模式

    操作系统--让操作系统走进保护模式 实验内容: 向软盘镜像文件写入一个你指定的文件,手工读取在磁盘中的信息 在软盘中找到指定的文件,读取其扇区信息 将指定文件装入指定内存区,并执行 学会在bochs中 ...

  3. 【OS学习笔记】二十五 保护模式七:任务和特权级保护对应的汇编源代码

    本汇编代码是以下两篇文章讲解的内容的内核代码; [OS学习笔记]二十三 保护模式七:保护模式下任务的隔离与任务的特权级概念 [OS学习笔记]二十四 保护模式七:调用门与依从的代码段----特权级保护 ...

  4. 【OS学习笔记】三十五 保护模式十:中断描述符表、中断门和陷阱门

    上一篇文章学习了中断与异常的概念:[OS学习笔记]三十四 保护模式十:中断和异常区别 本片文章接着学习以下内容: 中断描述符表 中断门 陷阱门 1 中断描述符表 我们前面讲了无数次,在实模式下,是由位 ...

  5. 【OS学习笔记】十五 保护模式三:保护模式下的内存访问机制

    上一篇文章学习了段描述符与段描述符各个标志位的含义:段描述符 本篇文章学习如何进入保护模式,并学习如何在保护模式下进行内存访问. 1.如何进入保护模式 假设我们已经用汇编语言将段描述符安装到GDT中( ...

  6. 自己动手写操作系统--搭建保护模式下的运行环境:bochs下安装freedos

    在进行保护模式的运行环境配置前,先看了了下书上的代码,编译运行结果如下:nasm 3_pmtest1.asm -o pmtest1.bin,可以看到界面出现了红色的 p 字 保护模式环境配置 1:在网 ...

  7. c语言取模原理,字符取模显示原理

    n年前写的,现在忘了,来回顾一下: 下面主要对字符的编码,即把字符转化为字节数组,字符如何显示在屏幕上即字符解码工作做了一些原理性分析,虽然有很多编码和解码方式,这是其中一种,但是最终目的是一样的,就 ...

  8. 操作系统开发系列—2.进入32位保护模式

    源码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3 ...

  9. 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表

    学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...

最新文章

  1. ArcGIS Server的配置
  2. 《SAS编程与数据挖掘商业案例》学习笔记之十五
  3. IOS简单的登陆界面
  4. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第5篇]复杂性类NP是什么意思?
  5. 拯救者 linux 无线网卡驱动下载,联想y7000无线网卡驱动下载-联想拯救者y7000无线网卡驱动v19.51.22.2 官方版 - 极光下载站...
  6. 云南昆明美容美发店务管理软件
  7. C Library User 手册(25)
  8. Linux:移植ffmpeg到ARM板(含x264编译步骤)
  9. 机器学习——PCA(主成分分析)与人脸识别
  10. 如何手机桌面加计算机,教你自制手机、电脑壁纸|手机一键加字、加光晕特效,4步搞定!...
  11. 支付宝服务商模式支付
  12. The server time zone value ‘� й ��� ׼ʱ ��‘ is unrecognized or represents more than one time zone.
  13. 【Flink】参数不生效
  14. 从零入门云计算(1):云计算究竟是个啥?
  15. 文件管理系统(操作系统)——9张思维导图
  16. 计算机初级考试题库网络管理,计算机基础考试题库(含答案)【精】.doc
  17. 矩形图:数据之美在图形中展现
  18. 直至现在,还是有很多人分不清登录与登陆
  19. NSI8121N0应用的一些心得
  20. 阅后即焚?就问截屏你怕不怕?

热门文章

  1. 【java】for循环的应用
  2. android 连接ble键盘,如何在Android上以编程方式配对和连接HID蓝牙设备(蓝牙键盘)...
  3. 发那科程序全部输出_走,去看看发那科机器人全新的自动化解决方案!
  4. 《R语言预测实战》PDF,数据及代码
  5. python爬虫有道词典_Python爬取有道词典,有道的反爬很难吗?也就这样啊!
  6. hmm 求隐藏序列_自然语言处理(3)隐马尔科夫模型 HMM
  7. linux svn 自动启动,Linux下设置svn开机自启动
  8. tensorflow支持python3.7吗_前端开发行业真的会被AI取代吗?
  9. a大于10小于15C语言,计算机基础复习模拟试卷
  10. jedis操作set_Jedis的学习