• 自制操作系统日志——第十四天


    自制操作系统日志——第十四天

    今天主要的任务是给我们的分辨率升升级!然后,将继续开发出一个输入栏,以供我们随意的进行输入并删除数据。



    前言

    在前面几天呢,我们总是能看到我们再进行不断的优化代码,不断的加快一下中断的执行速度!这一些如此细微的改动,也许我们可能会觉得没什么必要。但是,要知道随着我们后面不断的开发,以及多任务下更多程序的介入,我们之前所作的一些优化的效果将会越来越重要。就比如,我们对于中断速度的优化,在后期当同时一很多中断发生时,这些优化后精进的速度,将会使得我们系统的反应能力大幅度的提高!!!

    接着,我们已经大约度过了两周的时间了!!前两周我们对于开发操作系统所需的编程语言的学习呀,算法技巧的学习呀等等都已经大致的学完了。那么,此后就可以好好的利用其前面所学的继续我们的完善之路。然后,就是说前面13天的内容也是十分的重要且有意义的,希望我能够继续好好的多品味品味!!!


    一、提高分辨率

    在这之前我们使用的显卡模式主要是VGA模式,其分辨率主要是320x200x8的模式!!那么这一个分辨率明显是有所不足的!因此啊,下面我们将利用VBE模式下进行设置!

    首先,VBE是多家显卡公司一起协商制定的统一显卡的设定标准。他们专门的制作了一个BIOS进行设定,以此来解决不同显卡设定、接口不同的问题。因此,以下我可能会使用VBE2.0以上的BIOS显卡设定,如果真机(vmware)不支持此类设定的话,那就只能继续使用VGA显卡了!

    非VBE画面模式的设定:
    AH=0; 调用0号子中断程序
    AL = 画面模式号码

    VBE画面模式的设定:
    AX = 0x4f02
    BX = 画面模式的设定
    画面模式设定信息:
    0x101 ⇒ 640x480x8
    0x103 ⇒ 800x600x8
    0x105 ⇒ 1024x768x8
    0x107 ⇒ 1280x1024x8
    在实际设定时一般还要加上0x4000后再赋值到bx中。
    画面模式的存储信息内容:
    word [es:di + 0x00] ⇒ 模式属性 …其中存储的bit7(第七位)上如果是1 则代表可以加上0x4000后进行传入!!!
    word [es:di + 0x12] ⇒ x的分辨率
    word [es:di + 0x14] ⇒ y的分辨率
    byte [es:di + 0x19] ⇒ 颜色数…必须是8
    byte [es:di + 0x1b] ⇒ 颜色指定方法,必须是4 (4 指调色板模式)
    dword [es:di + 0x12] ⇒ VRAM地址
    其中,es的段地址应该是:0x9000
    那么以下,就让我们开始修改asmhead.nas:

    我们主要做如下的工作:以下所采用中断后,读取的信息都会存入到90000:0000之中!

    1. 确认VBE是否存在,通过调用int 0x10 以及利用ax值是否改变进行确认;
    2. 确认版本,通过读取1中存取的信息来进行比较;
    3. 读取画面模式,并存入对应的内存之中;
    4. 进行画面模式的确认,确认颜色数是否为8,是否为调色版模式,是否模式属性的bit7位置上是1;
    5. 进行画面的切换;
    6. 如果以上有一个不行就跳转到此,恢复VGA 320x200x8模式
    [INSTRSET "i486p"]
    
    VBEMODE	EQU		0x105
    
      ORG 0xc200 ;程序最终被装载到内存的地址
        ;0x8000+0x4200=0xc2000;0x8000是内存存放软盘的地址,0x4200是软盘存放文件的地方
    
    ;确认VBE是否存在
        MOV AX,0x9000
    	MOV ES,AX
    	MOV DI,0
    	MOV AX,0X4f00;有vbe的话值会自动编程0x004f
    	INT 0x10  ;取得的数据也是放在es:di中
    	CMP AX,0x004f
    	JNE scrn320
    ;确认VBE版本,非2.0版本不能使用高分辨率
        MOV AX,[ES:DI+4]
    	CMP AX,0x0200
    	JB scrn320
    ;取得画面模式信息,这里的数据将会被放在es:di开始的256字节中
        MOV CX,VBEMODE
    	MOV AX,0x4f01
    	INT 0x10
    	CMP AX,0x004f
    	JNE scrn320
    ;画面模式信息确认
        CMP BYTE [ES:DI+0x19],8
    	JNE scrn320
    	CMP BYTE [ES:DI+0x1b],4
    	JNE scrn320
    	MOV AX,[ES:DI+0x00]
    	AND AX,0x0080 
    	JZ  scrn320
    ;画面模式切换
        MOV BX,VBEMODE+0x4000 
    	mov AX,0x4f02 ;
        int 0x10
        mov byte [VMODE],8  ; 屏幕的模式(参考C语言的引用)
    	MOV	AX,[ES:DI+0x12]
    	MOV	[SCRNX],AX
    	MOV	AX,[ES:DI+0x14]
    	MOV	[SCRNY],AX
    	MOV	EAX,[ES:DI+0x28]
    	MOV	[VRAM],EAX
    	JMP	keystatus
    
    scrn320:
    	MOV	AL,0x13			; VGA模式, 320x200
    	MOV	AH,0x00
    	INT	0x10
    	MOV	BYTE [VMODE],8	; 记下画面模式,参考c
    	MOV	WORD [SCRNX],320
    	MOV	WORD [SCRNY],200
    	MOV	DWORD [VRAM],0x000a0000
    	
    keystatus:
    ;用BIOS取得键盘上各种LED指示灯的状态
        mov ah,0x02 
        int 0x16 ;键盘BIOS
        mov [LEDS],al
    
    • 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
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    然后,让我们make run一下看看!!
    在这里插入图片描述
    很棒,明显vmwar是支持的,那么至此我们就可以进入高分辨率的模式了!!!

    二、增加键盘输入字符功能

    1.输入单个字符

    首先,我们打开该系统,可以发现再我们之前所作的设置里,当我们按下键盘的a时,按下是弹出1E,按起后弹出的就是9e。在书本里作者给我们罗列了很多按下键时的值。然后我们只需在此基础上+0x80就为按其后的值了!!

    之所以会有两个值,也是因为方便告诉计算机:我按下了这个键,以及我松开了这个键。方便计算机知道什么时候开始,什么时候结束!!
    在这里插入图片描述
    然后,针对此我们进行更改一下主函数:

    	if (fifo32_status(&fifo) == 0)
    		{
    			io_stihlt();
    		}else 
    		{ 
    			i = fifo32_get(&fifo);
    			io_sti();
    			if (256 <= i && i <= 511) { /*键盘数据 */
    				sprintf(s, "%02X", i - 256);
    				putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
    				if( i == 0x1e + 256)
    				{
    					putfonts8_asc_sht(sht_win, 40, 28, COL8_000000, COL8_C6C6C6, "A", 1);
    				}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    哇哦,成功了!!

    那么,继续再接再励,做一个输入框,然后可以任意输入数据并删除输入吧!!

    2.输入框制作

    根据上述的按下时的字符编码,我们在主函数中制作如下的数据:

       	static char keytable[0x54] = {
    		0,   0,   '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 0,   0,
    		'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 0,   0,   'A', 'S',
    		'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0,   0,   ']', 'Z', 'X', 'C', 'V',
    		'B', 'N', 'M', ',', '.', '/', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
    		0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
    		'2', '3', '0', '.'
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后进一步的我们增加输入框以及实现输入删除的功能:(这其中涉及了光标的显示)

    	int mx,my,i, cursor_x, cursor_c   ;make_textbox8(sht_win, 8, 28, 144, 16, COL8_FFFFFF);
    	for(;;)   
    	{
    		io_cli(); //IF=0
    		if (fifo32_status(&fifo) == 0)
    		{
    			io_stihlt();
    		}else 
    		{ 
    			i = fifo32_get(&fifo);
    			io_sti();
    			if (256 <= i && i <= 511) { /*键盘数据 */
    				sprintf(s, "%02X", i - 256);
    				putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
    				if( i < 0x54 + 256)
    				{
    					if(keytable[i-256] != 0 && cursor_x < 144) //一般字符
    					{//显示一个字符光标就向前移动一次
    						s[0] = keytable[i-256];
    						s[1] = 0;
    						putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_C6C6C6, s, 1);
    						cursor_x +=8;
    					}
    					if(i == 256 + 0x0e && cursor_x > 8) //退格键
    					{//用空格把光标消去后移动一次
    						putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1);
    						cursor_x -=8;
    					}
    					//光标在显示
    					boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
    				    sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
    				}
    
    • 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

    然后是输入框的代码:

    //x0,y0是起始位置 ,sx是长度,sy是宽度
    void make_textbox8(struct SHEET *sht, int x0, int y0, int sx, int sy, int c)
    {
    	int x1 = x0 + sx, y1 = y0 + sy;
    	boxfill8(sht->buf, sht->bxsize, COL8_848484, x0 - 2, y0 - 3, x1 + 1, y0 - 3);
    	boxfill8(sht->buf, sht->bxsize, COL8_848484, x0 - 3, y0 - 3, x0 - 3, y1 + 1);
    	boxfill8(sht->buf, sht->bxsize, COL8_FFFFFF, x0 - 3, y1 + 2, x1 + 1, y1 + 2);
    	boxfill8(sht->buf, sht->bxsize, COL8_FFFFFF, x1 + 2, y0 - 3, x1 + 2, y1 + 2);
    	boxfill8(sht->buf, sht->bxsize, COL8_000000, x0 - 1, y0 - 2, x1 + 0, y0 - 2);
    	boxfill8(sht->buf, sht->bxsize, COL8_000000, x0 - 2, y0 - 2, x0 - 2, y1 + 0);
    	boxfill8(sht->buf, sht->bxsize, COL8_C6C6C6, x0 - 2, y1 + 1, x1 + 0, y1 + 1);
    	boxfill8(sht->buf, sht->bxsize, COL8_C6C6C6, x1 + 1, y0 - 2, x1 + 1, y1 + 1);
    	boxfill8(sht->buf, sht->bxsize, c,           x0 - 1, y0 - 1, x1 + 0, y1 + 0);
    	return;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    三、增加拖动窗口功能

    这里我们先简单制作一个拖动窗口的功能,即按下鼠标左键就会显示窗口的位置!!

    这里由于我们之前已经利用过图层来显示了,因此,这里的拖动,我们仅仅只需将图层位置和鼠标关联一下即可:

    if (my > binfo->scrny - 1) {
    						my = binfo->scrny - 1;
    					}
    					sprintf(s, "(%3d, %3d)", mx, my);
    					putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
    					sheet_slide(sht_mouse, mx, my);
    					if((mdec.btn & 0x01) != 0)//按下左键,移动窗口
    					{
    						sheet_slide(sht_win, mx - 80, my - 8);
    					}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述


    总结

    以上就是我们今天进行内容,主要就是将分辨率进行了提高,然后还利用图层技术实现了简单的拖动功能!!!以及字符串的输入等等。

    已经越来越像一个小型的操作系统了,继续努力加油!!

  • 相关阅读:
    Redisson 限流器源码分析
    PHP 函数
    docker-compose安装RabbitMQ
    Selenium基础 —unittest单元测试框架
    前端学习C语言 - 初级指针
    实体机 安装 centos
    FastJson 漏洞复现
    px4仿真实现无人机自主飞行
    2023年中国一次性塑料餐具市场供需现状、市场规模及行业发展前景分析[图]
    二阶段day6
  • 原文地址:https://blog.csdn.net/qq_43696276/article/details/126069153