自制操作系统日志——第八天

自制操作系统日志——第八天

今天,就让我们把鼠标动起来,以及解释一下之前遗留的代码理解。



一、鼠标数据的解读

首先,为了能够更好的了解我们移动鼠标时候,产生的数据有什么作用,这里我们将把 鼠标收到的数据显现出来,然后,移动鼠标看看:
主函数部分:

	unsigned char mouse_dbuf[3], mouse_phase;

	enable_mouse();
	mouse_phase = 0;

	for (;;) {
		io_cli();
		if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
			io_stihlt();
		} else {
			if (fifo8_status(&keyfifo) != 0) {
				i = fifo8_get(&keyfifo);
				io_sti();
				sprintf(s, "%02X", i);
				boxfill8(binfo->vram, binfo->scrnx, COL8_008484,  0, 16, 15, 31);
				putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
			} else if (fifo8_status(&mousefifo) != 0) {
				i = fifo8_get(&mousefifo);
				io_sti();
				if (mouse_phase == 0) {
					if (i == 0xfa) {
						mouse_phase = 1;
					}
				} else if (mouse_phase == 1) {
					mouse_dbuf[0] = i;
					mouse_phase = 2;
				} else if (mouse_phase == 2) {
					mouse_dbuf[1] = i;
					mouse_phase = 3;
				} else if (mouse_phase == 3) {
					mouse_dbuf[2] = i;
					mouse_phase = 1;
				  sprintf(s, "%02X %02X %02X", mouse_dbuf[0], mouse_dbuf[1], mouse_dbuf[2]);
					boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 8 * 8 - 1, 31);
					putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
				}
			}
		}
	}
}

这里,我们利用phase这个标志,来将鼠标最初读到的数据,即0xfa进行丢弃,然后利用下面的3个if语句进行将鼠标的三个数据显示出来。
在这里插入图片描述

你的屏幕上可能会出现类似08 00 00这三个数据:
08 中的 0 会在0~3范围内变动;
08 中的 8 是与鼠标点击有关;
第一个00 是与 鼠标的左右移动有关
第二个00 是与 鼠标的上下移动有关。

好了,再解读完这些数据后,我们进行一下修改,优化一下我们之前所写的代码,方便后续进行鼠标的移动处理:
bootpack.c:

struct MOUSE_DEC
{
	unsigned char buf[3],phase;
	int x, y, btn;//x,y移动信息,btn是按键状态
};
for(;;)
{.....
 else if (fifo8_status(&mousefifo) != 0) {
				i = fifo8_get(&mousefifo);
				io_sti();
				if (mouse_decode(&mdec, i) != 0) {
					/* ƒf[ƒ^‚ª3ƒoƒCƒg‘µ‚Á‚½‚Ì‚Å•\Ž¦ */
					sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
					if ((mdec.btn & 0x01) != 0) {
						s[1] = 'L';
					}
					if ((mdec.btn & 0x02) != 0) {
						s[3] = 'R';
					}
					if ((mdec.btn & 0x04) != 0) {
						s[2] = 'C';
					}
					boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
					putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
				}
			}
}

int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{
	if (mdec->phase == 0) {
		/*等待鼠标的0xfa阶段,舍弃激活后的答复0xfa */
		if (dat == 0xfa) {
			mdec->phase = 1;
		}
		return 0;
	}
	if (mdec->phase == 1) {
		/* 等待鼠标第一字节 */
		if((dat & 0xc8) == 0x08)
		{//如果第一字节正确的话
			mdec->buf[0] = dat;
		    mdec->phase = 2;
		}
		return 0;
	}
	if (mdec->phase == 2) {
		/* 等待鼠标第二字节 */
		mdec->buf[1] = dat;
		mdec->phase = 3;
		return 0;
	}
	if (mdec->phase == 3) {
		/* 等待鼠标第三字节*/
		mdec->buf[2] = dat;
		mdec->phase = 1;

		mdec->btn = mdec->buf[0] & 0x07; //鼠标按键状态是在buf[0]的低三位,因此只取出这一部分即可
		mdec->x = mdec->buf[1];
		mdec->y = mdec->buf[2];

		if((mdec->buf[0] & 0x10) != 0)
		{
			mdec->x |= 0xffffff00;//xy的左右移动信息就只有8位,因此用这个方法取出即可
		}
		if((mdec->buf[0] & 0x20) != 0)
		{
			mdec->y |= 0xffffff00;
		}
		mdec->y = - mdec->y;//鼠标的y方向与屏幕的y方向相反
		return 1;
	}
	return -1; /* 应该不会来这的,鼠标激活了就会传送数据的 */
}

代码中,鼠标在接收第一个字符的那里,进行判断的原因是: 鼠标数据的第一字节的数据变化范围应该是 [0~3] [8~f] 因此,只要这这个数据范围内的与0xc8相与后结果必是0x08 。

在这里插入图片描述

lcr 就是鼠标点击时出现的相应变化。

二、移动鼠标

由于有了鼠标解读后的数据,因此直接上代码:

else if(fifo8_status(&mousefifo) != 0)
		    {
		    	i = fifo8_get(&mousefifo);
				io_sti();
				if(mouse_decode(&mdec,i) != 0)
				{
				//凑齐三字节了进行输出!!
				sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
				if((mdec.btn & 0x01) != 0)
				{
					s[1] = 'L';
				}
				if((mdec.btn & 0x02) != 0)
				{
					s[3] = 'R';
				}
				if((mdec.btn & 0x04) != 0)
				{
					s[3] = 'C';
				}
				boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32+15*8 - 1, 31);
				putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
				//让鼠标动起来
				boxfill8(binfo->vram, binfo->scrnx, COL8_008484, mx, my, mx+15, my+15);//隐藏鼠标
				mx += mdec.x;
				my += mdec.y;
				if(mx < 0)
				{
					mx =0;
				}
				if(my < 0)
				{
					my = 0;
				}
				if(mx > binfo->scrnx - 16)
				{
					mx = binfo->scrnx - 16;
				}
				if(my > binfo->scrny - 16)
				{
					my = binfo->scrny - 16;
				}
				sprintf(s,"(%3d,%3d)", mx, my);
				boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 0, 79, 15);//隐藏坐标
				putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);//显示坐标
				putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);//描绘图像
				}
		    }

在后面的if那里,是为了防止鼠标跑到屏幕外的!!
在这里插入图片描述

三、解读通往32位的那部分代码

这里,首先参考一下别人对操作系统启动的解释:https://max.book118.com/html/2018/0401/159613305.shtm

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

⇒ ipl10.nas 在一开始时位于软盘的第一个扇区之中,然后我们启动机器:
⇒ 会先读软盘第一个扇区的末尾,检测到 55 aa 然后就开始装载和读取我们第一个扇区的内容,此时该区内容(ipl) 就会加载到0x7c00处的内存区域。 (由于此时处于实模式下,可用的内存区域为1MB ,需进入到保护模式的32位模式下)
⇒ 然后ip10.nas会读取软盘的内容到内存中去,然后再跳转到sys这个系统程序当中:
⇒ 首先指向asmhead.nas 该文件保存一些bios相关数据,然后启动32位的保护模式,并将原先的数据全部转移至对应的32位下的物理内存当中,:
⇒ 紧接着就开始处理bootpack.hrb的内容了。。

至于代码的解释,我已经写了详细的说明再代码之中,结合最近的中断内容一起进行理解即可。。


总结

今天任务大致就是这些了,先好好消化一下,然后继续开发吧!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值