【操作系统】30天自制操作系统--(7)鼠标移动与32位切换

本文详细介绍了如何在操作系统中处理鼠标和键盘的中断,特别是鼠标中断中的操作码解析,用于实现鼠标的移动。通过读取鼠标中断中的三位信息,解析出X、Y坐标和按键状态,实现实时显示鼠标操作。同时,文章提到了32位切换的内容,但未深入展开。最后展示了实际运行效果,尽管存在重绘导致的界面问题,但总体实现了基本的鼠标交互功能。
摘要由CSDN通过智能技术生成

        上一章介绍了键盘与鼠标的中断以及操作码的读入,这一章将用鼠标的操作码,结合之前绘制的鼠标箭头,实现鼠标的移动。另外,再说明一下前文略过的asmhead.nas的内容。

一 鼠标移动

        鼠标在中断中的存储的操作码包含三位的信息,即[操作,X坐标,Y坐标],我们在主函数中读取的时候,可以三位三位地读取。

        这边鼠标数据的解读分为三个阶段,首先要把最初读到的0xfa舍弃掉。之后,每次从鼠标那里送过来的数据都应该是3个字节一组的,所以每当数据累 积到3个字节,就把它显示在屏幕上

        对鼠标数据的解读如下:

struct MOUSE_DEC {
    unsigned char buf[3], phase;
};

void HariMain(void)
{
    //(中略)
    struct MOUSE_DEC mdec;
    //(中略)
    enable_mouse(&mdec);
    for (;;) {
	    io_cli();
        if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
            io_stihlt();
        } else {
            if (fifo8_status(&keyfifo) != 0) {
                // 键盘的操作
            } else if (fifo8_status(&mousefifo) != 0) {
                i = fifo8_get(&mousefifo);
                io_sti();
                if (mouse_decode(&mdec, i) != 0) {
                    /* 3字节都凑齐了,所以把它们显示出来*/
                    sprintf(s, "%02X %02X %02X", mdec.buf[0], mdec.buf[1], mdec.buf[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);
                }
            }
        }
    }
}


/**
 * @brief 获取鼠标状态
 */
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{
	if (mdec->phase == 0) {
		/* 等待鼠标的0xfa的阶段 */
		if (dat == 0xfa) {
			mdec->phase = 1;
		}
		return 0;
	}
	if (mdec->phase == 1) {
		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;
		return 1;
	}
	// shit value
	return -1;
}

        再从上面接收到地模糊信息中提取到鼠标真正地操作信息(扩充 struct MOUSE_DEC 中的信息,加入 x, y, btn 表示移动信息和鼠标按下的状态):

struct MOUSE_DEC {
    unsigned char buf[3], phase;
	int x, y, btn;
};

if (mdec->phase == 3) {
    mdec->buf[2] = dat;
    mdec->phase = 1;
    // 取出低三位就是按键的状态
    mdec->btn = mdec->buf[0] & 0x07;
    mdec->x = mdec->buf[1];
    mdec->y = mdec->buf[2];
    if ((mdec->buf[0] & 0x10) != 0) {
    mdec->x |= 0xffffff00;
    }
    if ((mdec->buf[0] & 0x20) != 0) {
    mdec->y |= 0xffffff00;
    }
    mdec->y = - mdec->y;
    return 1;
}

        在主函数中,将鼠标的操作具象地打印出来,原本显示lcr,当左键按下,l变成L,当右键按下,r变成R,当中键按下,c变成C:

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[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);
}

        鼠标的移动就更简单了,原理就是在中断中读取到鼠标的最新位置处,重绘鼠标的图形区域。

	/* 显示鼠标图形 */						
	// 隐藏鼠标
    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); 

        实际运行效果如下:

         由图中可以看出,界面中的鼠标能够很好地响应实际鼠标的操作,包括点按操作和位置移动。但是仍有不足,就是当鼠标移动到下面菜单栏时,重绘的操作会将下面菜单栏也一并重绘了,具体的解决办法在后面的重叠区域处理中会有介绍,这边就不展开讲了。

二 32位切换

        历史遗留问题,阐述了asmhead.nas中新添加的100多行内容的具体含义(大意就是按照一定的步骤将某些寄存器(CR0等)设置为特定的值),这边比较难懂,而且感觉也没有必要全搞懂,这边就贴一张作者目前操作系统设计的内存分布图:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值