欲观看本章代码效果,请参看视频:
Linux kernel Hacker, 从零构建自己的内核

当我们获得鼠标发送的数据后,我们就可以根据相应的信息绘制鼠标,从而实现鼠标的挪动效果,在此之前,我们得了解,鼠标发送的数据是怎么解读的。

鼠标发送的数据,必须三个字节连在一起解读,所以我们的内核要等待鼠标发送足够的数据后才可以采取行动。前面我们看到,当鼠标被激活后,它会立马给内核发送一个字节数据,数值为0xfa, 当内核收到这个数据后,就可以开始积攒数据,每接收三个字节后,根据数据绘制鼠标。

这三个字节数据是有一定特点的,第一个字节0xab, a的数值必须在0-3这个范围内,由于a对应的是八比特中的高四位,所以这意味着该字节的第7,8两个比特位必须为0,b对应着八比特位中的低四位,它的值必须在8-F之间,这意味着该字节数据对应的第4个比特位必须为1.把第一个字节转换成二进制,那么它必须满足下面格式(X,*代表0或1):
0 0 X X 1 * \ * *
三个*用来表示鼠标按键,当鼠标的左键,滚轮,右键被按下时,对应的比特位会设置为1.

第二个字节用来表示鼠标的左右移动,对该字节进行相应处理后,可以得到鼠标平移的坐标变换。

第三个字节的数据表示鼠标的上下移动,对该字节进行相应处理后,可以得到鼠标垂直移动时的坐标数变化。

我们专门设置一个结构体来处理鼠标发送的相关信息:

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

buf[3]用来存储鼠标发送的三个数据,phase表示当前接收到第几个数据了,x表示水平移动的坐标变换,y表示上下移动时鼠标的坐标变换,btn用来表示鼠标哪个按键被按下了。

内核中增加一个函数来解析鼠标发送的数据:

int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat) {if (mdec->phase == 0) {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;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;}return -1;
}

当收到字节0xfa的时候,系统进入数据收集阶段,当收到第一个数据时,判断字节是否符合前面所说的要求,符合的话,进入第二阶段,接收第二个字节,当进入第三阶段,接收完第三个字节后,开始对坐标数据进行处理,btn存储的是第一字节的低3位,它表示当前鼠标哪个按键被按下了,接着看第一字节的第5,第6个比特位,如果第5个比特位设置为1,那么第二字节需要做一些处理,也就是从第8位开始全部设置为1,至于为何要这么做,我们暂且不用关心,同理,如果第6个比特位设置为1,那么把第3个字节做一些处理才得到鼠标的垂直变换。

由于鼠标给的垂直变换跟我们屏幕坐标是相反的,所以y值要去反。通过这一步我们就解析了鼠标发送过来的数据。

在内核主函数中,我们要根据鼠标传输的数据重新绘制鼠标:

static int mx = 0, my = 0;
void CMain() {....mx = (xsize - 16) / 2;my = (ysize - 28 - 16) / 2;  init_mouse_cursor(mcursor, COL8_008484);putblock(vram, xsize, 16, 16, mx, my, mcursor, 16);.....else if (fifo8_status(&mouseinfo) != 0) {show_mouse_info();}
}void computeMousePosition(struct MOUSE_DEC* mdec) {mx += mdec->x;my += mdec->y;if (mx < 0) {mx = 0;}if (my < 0) {my = 0;}if (mx > xsize - 16) {mx = xsize - 16;}if (my > ysize - 16) {my = ysize - 16;}}void eraseMouse(char* vram) {boxfill8(vram, xsize, COL8_008484, mx, my, mx+15, my+15);
}void drawMouse(char* vram) {putblock(vram, xsize, 16, 16, mx, my, mcursor, 16);
}void  show_mouse_info(void) {char*vram = bootInfo.vgaRam;unsigned char data = 0;io_sti();data = fifo8_get(&mouseinfo);if (mouse_decode(&mdec, data) != 0) {eraseMouse(vram);computeMousePosition(&mdec);drawMouse(vram);}
}

eraseMouse 作用是使用桌面的背景颜色将鼠标抹掉, drawMouse是根据鼠标新的坐标重新绘制鼠标图案,show_mouse_info里,先将通过mouse_decode获得鼠标数据,然后通过调用eraseMouse将鼠标在当前位置抹掉,computeMousePosition重新计算鼠标移动后的新位置,drawMouse根据新位置重新绘制鼠标。

将上面的C语言编译,然后反编译成汇编后,加入内核汇编模块,编译时会出现类似这样的错误:
error: short jump is out of range

这是因为在汇编语言中,跳转指令,例如jmp, jne等,跳转的距离不能超过127字节,但是由于我们现在的C语言使用了结构体等复杂数据结构,反汇编后,汇编代码语句会增多,从而造成jmp等指令所要跳转的目的地与当前指令间的距离超过127字节,解决办法是在指令出错的地方增添一个near关键字,例如语句:
jmp ?0_57
改成
jmp near ?0_57
那么上面错误就可以消除了,内核编译并加载如虚拟机后,鼠标便能灵动起来:

博客无法显示动态效果,请大家观看视频。

系统内核的洪荒之力:挪动鼠标相关推荐

  1. 与微软.NET创始人Scott Guthrie面对面,“红衣教主”亲身传授推动成功转型的洪荒之力

    金秋九月,是个即将收获的季节.微软 2016 企业技术决策论坛将于2016年9月21日在北京召开.届时,技术大咖Scott Guthrie 将现身论坛,和嘉宾们现场交流互动. 说起 Scott Gut ...

  2. 以洪荒之力打开linux德·摩根定律

    德·摩根定律让学习liunx的小伙伴绕得头疼,现在我就用洪荒之力为大家理顺一下这个定律. 由图片可以看出, A=4+3 B=3+2 非A=2+1 非B=4+1 A且B就是代表既是A又是B的地方,A和B ...

  3. 2016程序员你该爆发洪荒之力了!八招教你成功

    你在白天的办公室里谈笑风生,我在黑夜的出租屋里敲出人生,不要问一个苦逼的程序员未来如何?只想说,我的梦想就像乔布斯一样"改变世界",改变人生--从码农到成功创业者的宝贵经验,八条成 ...

  4. Coding哥,魅族让你用洪荒之力来夺宝了!

    曾经也是Coding哥的小编以前有一个梦想,就是靠编程哪天也能像"中国好声音"里的歌手一样一夜成名,名利双收!可现实是残酷的,一直到小编离开编程这个行当,这个梦想也木有实现,给小编 ...

  5. 洪荒之力的英语翻译(mystical powers)

    洪荒之力  英文 ("mystical powers" ), literally: power strong enough to change the universe. 中文意思 ...

  6. 【2017.12.09】安卓巴士全球开发者论坛广州站 ——全面开启安卓洪荒之力

    2017安卓巴士全球开发者论坛 --全面开启安卓洪荒之力 12月09日 · 广州站 主办方:安卓巴士(中国最大的安卓开发者社区http://www.apkbus.com) 现场有奖小活动预告 1.现场 ...

  7. 洪荒之力已无,追求之心尚在

    一.致谢 我的第一本习作<Hadoop构建数据仓库实践>出版了.感谢CSDN博客提供的技术学习平台,能让我把自己平时积累的技术心得加以总结,形成一篇篇博文与人分享.正因如此才有了将博文整理 ...

  8. 探索挖掘数据的洪荒之力

    9月12日-9月14日,2016中国(北京)国际大数据产业博览会暨高峰论坛,在北京·中国国际展览中心举行.本届展会以"促进大数据时代变革.共赢新时代机遇和挑战"为主题,展示了大数据 ...

  9. DeepTables: 为结构化数据注入深度学习的洪荒之力

    近年来深度学习在CV.NLP等非结构化领域展现出超强的统治力,突破最高水平的算法层出不穷.深度学习在结构化和非结构化领域表现出来的巨大反差已成为热门话题,自从以XGBoost.LightGBM为代表的 ...

最新文章

  1. 一文弄懂YOLO目标检测算法
  2. JZOJ 5982. 【WC2019模拟12.27】路径排序
  3. 【网址收藏】dubbo特新概念及特性、环境搭建、dubbo-monitor安装、rpc原理以及dubbo原理:框架设计、启动解析加载配置信息、服务暴露、服务引用及调用
  4. Thread和Runnable的区别和联系、多次start一个线程会怎么样
  5. php7.1 aes 加密解密,PHP7.1中AES加密解密方法 mcrypt_module_open()替换方案
  6. 【C】@程序员,我们送给你一个成熟的Excel导入导出组件
  7. bind_param 类怎么写_情感类自媒体怎么写?你不知道的情感类文章4大禁忌!
  8. 《请君入瓮——APT攻防指南之兵不厌诈》目录—导读
  9. idea 2021版本错误提示反应慢
  10. 隐性代言vancl 徐静蕾卖的不只是项链?
  11. java完成九宫格数独_简单实现java数独游戏
  12. 程序员的呐喊--读书感悟
  13. metamask 最新版官方版
  14. iphone7运行linux,我在iPhone7装入了Linux系统!
  15. mysql on delete_MySQL ON DELETE CASCADE
  16. 前端接收bolb格式下载文件,前端下载blob格式的文件
  17. 从今天开始—兄弟连IT教育
  18. windows下jenkins执行shell报错
  19. JAVA计算机毕业设计二手车交易市场网站Mybatis+源码+数据库+lw文档+系统+调试部署
  20. Docker之镜像操作

热门文章

  1. 乐蒙网:IE 浏览器进入死亡倒计时,Microsoft Edge 能否接过大旗?
  2. RESTful API 设计、文档生成、测试
  3. (附源码)springboot教师排课课系统 毕业设计 310858
  4. 参考文献可以自动生成
  5. 苹果手机清理缓存很麻烦?这样简单操作一下,一键能清出几个G缓存
  6. mincore\com\oleaut32\dispatch\ups.cpp(2122)\OLEAUT32.dll!00007FFD2D4A95F6: (caller: 00007FFD2D4A8A09
  7. java -jar no access_Unable to access jar file xxx.jar
  8. SaveClipBRO — 很强大的在线视频、音乐下载,提供在线转码
  9. 搜狐快站制作html,搜狐快站H5页面设计制作大赛,获奖作品第二弹!
  10. Apache网页的优化,安全与防盗链