鼠标解读
bootpack.c节选

mouse_phase = 0; /* 进入到等待鼠标的0xfa的状态 */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) //把最初读到的0xfa舍弃掉{/* 等待鼠标的0xfa的状态 */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;/* 鼠标的3个字节都齐了,显示处来 */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);}}}}


1、如果移动鼠标,08 中的0会在0~3的范围变化,如果仅仅移动鼠标,08中的8不变,如果按鼠标左键或右键,会在8~F变化
2、当鼠标左右移动时,00会变化
3、当鼠标上下移动是,01会变化

移动鼠标指针

bootpack.c节选

    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_decode(&mdec, i) != 0) {/* 数据的3个字节都齐了,显示处来 */sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);if ((mdec.btn & 0x01) != 0)  //如果第一位是1,说明按下左键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); /* 描画鼠标 */}}}}

make run之后可以看到鼠标可以移动了。

通往32位模式之路
asmhead.nas

; haribote-os boot asm
; TAB=4BOTPAK  EQU 0x00280000  ; bootpack.hrb(512KB)的开始地址
DSKCAC  EQU 0x00100000  ; 用于保存软盘内容(1440KB)的开始地址
DSKCAC0 EQU 0x00008000  ; 有关BOOT_INFO
CYLS    EQU 0x0ff0      ;设定启动区
LEDS    EQU 0x0ff1      ;键盘上各种LED指示灯的状态
VMODE   EQU 0x0ff2      ;有关颜色数目的信息
SCRNX   EQU 0x0ff4      ;分辨率的x
SCRNY   EQU 0x0ff6      ;分辨率的y
VRAM    EQU 0x0ff8      ;图像缓冲区的开始地址ORG     0xc200      ;程序要装载的地方MOV     AL,0x13     ;VGA显卡,32x00x8位颜色MOV     AH,0x00     ;设置AH=0x00,调用显卡BIOS函数,就可以切换显示模式了,AL中设置模式INT 0x10        MOV BYTE [VMODE],8    ; 记录画面模式MOV WORD [SCRNX],320MOV WORD [SCRNY],200MOV DWORD [VRAM],0x000a0000; 用BIOS取得键盘上各种LED指示灯的状态MOV AH,0x02INT 0x16        ; keyboard BIOSMOV [LEDS],AL; PIC关闭一切中断
;   根据AT兼容机的规格,如果要初始化PIC,
;   必须在CLT之前进行,否则有时会挂起
;   随后进行PIC的初始化MOV     AL,0xffOUT     0x21,AL     ; 禁止主PIC的全部中断NOP     ; 什么也不做,让CPU休息一个时钟的时间。如果连续执行OUT指令,有些机种会无法正常进行OUT     0xa1,AL     ; 禁止从PIC的全部中断CLI                 ; 禁止CPU级别的中断; 为了让CPU能够访问1MB以上的内存空间,设定A20GAECALL    waitkbdout  ; 等待KBC准备好MOV     AL,0xd1OUT     0x64,ALCALL    waitkbdout  MOV     AL,0xdf     ; 0xdf是让A20GATE信号线变成ON的状态,使内存1MB以上的部分变成可使用状态OUT     0x60,ALCALL    waitkbdout; 切换到保护模式。应用程序既不能随意改变段的设定,也不能使用操作系统专用的段,操作系统受CPU保护。[INSTRSET "i486p"]              ; “想要使用486指令”的叙述。INSTRSET指令,是为了能使用386以后的LGDT,EAX,CR0等LGDT    [GDTR0]     ; 设定临时GDTMOV     EAX,CR0     ; 将CR0这一特殊的32位寄存器的值代入EAX。CR0 control register0 只有操作系统可使用AND     EAX,0x7fffffff  ; 设bit31为0(为了禁止分页)OR      EAX,0x00000001  ; 设bit0为1(为了切换到保护模式)MOV     CR0,EAX     ; 完成模式转换JMP     pipelineflush   ; 当CPU切换到保护模式后时,要马上执行JMP指令。因为切换到保护模式后,
;机器语言的解释要发生变化,为了加快指令的执行而采用了管道机制。
pipelineflush:MOV     AX,1*8      ; 可读写的段32bitMOV     DS,AX       ; 进入保护模式后,除CS外,所有的段寄存器的值都从0x0000变成了0x0008,相当于gdt+1段MOV     ES,AXMOV     FS,AXMOV     GS,AXMOV     SS,AX; bootpack的转送
; 相当于memcpy(bootpack, BOTPAK, 512*1024/4),将bootpack.hrb复制到0x00280000号地址MOV     ESI,bootpack    ; 转送源MOV     EDI,BOTPAK      ; 转送目的地 MOV     ECX,512*1024/4  ; 传送数据的大小以双字节大小为单位,所以要/4CALL        memcpy; 磁盘数据最终转送到它本来的位置去; 首先从启动区开始; 相当于memcpy(0x7c00, DSKCAC, 512/4)MOV     ESI,0x7c00  ; 转送源MOV     EDI,DSKCAC  ; 转送目的地,0x00100000MOV     ECX,512/4CALL        memcpy; 所有剩下的; 相当于memcpy(DSKCAC0+512, DSKCAC+512, cyls*512*18*2/4-512/4)MOV     ESI,DSKCAC0+512 ; 转送源, 0x00008200MOV     EDI,DSKCAC+512  ; 转送目的地, 0x00100200MOV     ECX,0MOV     CL, BYTE [CYLS]IMUL        ECX,512*18*2/4  ; 从柱面数变成字节数. IMUL是整数乘法SUB     ECX,512/4   ; 减去IPLCALL        memcpy; 必须由asmhead来完成的工作,至此全部完毕
; 以后就由bootpack来完成; bootpack的启动。对bootpack.hrb的header部分进行解析,将执行所必需的数据传送过去。MOV     EBX,BOTPAK  ; q MOV     ECX,[EBX+16]ADD     ECX,3       ; ECX += 3;SHR     ECX,2       ; ECX /= 4;JZ      skip        ; 没有要传送的东西时MOV     ESI,[EBX+20]    ; 转送源ADD     ESI,EBXMOV     EDI,[EBX+12]    ; 转送目的地CALL        memcpy
skip:MOV     ESP,[EBX+12]    ; 栈初始值JMP     DWORD 2*8:0x0000001b  ; 将2*8代入到CS中,同时移动到0x1b号地址。waitkbdout:                 ; 与wait_KBC_sendready相同IN      AL,0x64AND     AL,0x02IN      AL,0x60     ; 空读,为了清空数据接收缓冲区中的垃圾数据JNZ     waitkbdout  ; AND结果如果不是0,就跳到waitkbdoutRETmemcpy:MOV     EAX,[ESI]ADD     ESI,4MOV     [EDI],EAXADD     EDI,4SUB     ECX,1JNZ     memcpy      ; 减法运算的结果如果不是0,就跳转到memcypRETALIGNB      16      ; 一直添加DBO,直到地址能被16整除的时候。如果标签GDT0的地址不是8的倍数,向段; 寄存器复制的MOV指令就会慢一些,所以加入了ALIGN指令
GDT0:                   ;GDT0是一种特定的GDT。0号是空区域,不能在那里定义段。RESB        8   ; NULL selectorDW      0xffff,0x0000,0x9200,0x00cf  ; 可以读写的段32bit。set_segmdesc(gdt+1, 0xffffffff, 0x00000000, AR_DATA32_RW)DW      0xffff,0x0000,0x9a28,0x0047  ; 可以执行的段32bit(bootpack用)。set_segmdesc(gdt+1, 0xffffffff, 0x00000000, AR_DATA32_RW)DW      0
GDTR0:                      ; 是LGDT指令,意思是通知GDT0,有了GDTDW      8*3-1       ; 写入16位段上限DD      GDT0        ; 写入32位段起始地址ALIGNB      16
bootpack:

HariMain节选

    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;char s[40], mcursor[256], keybuf[32], mousebuf[128];int mx, my, i;struct MOUSE_DEC mdec;init_gdtidt();  //GDT和IDT的初始化init_pic();     //PIC初始化io_sti();    //仅执行STI命令,IF变为1,CPU接收来自外部设备的中断fifo8_init(&keyfifo, 32, keybuf); fifo8_init(&mousefifo, 128, mousebuf);//PIC属于外部设备,用IN OUT指令进行操作io_out8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */io_out8(PIC1_IMR, 0xef); /* 开放鼠标中断(11101111) */init_keyboard();  //准备好鼠标控制电路init_palette();    //设置调色板init_screen(binfo->vram, binfo->scrnx, binfo->scrny);  //设置背景

总结一下切换到32位模式过程
1、初始化PIC,屏蔽所有中断,防止模式切换的过程中发生中断。
2、设定A20GATE,使CPU能访问1M以上的内存空间。
3、切换模式,设定临时GDT,将CR0最低一位设为1。
4、执行JMP指令,因为模式切换后要马上执行JMP指令,跳转到piplineflush段中,将除了CS以外的所有段寄存器都加8,相当于gdt+1段,因为进入保护模式后,段寄存器的解释不再是16倍,而是能够使用GDT
5、bootpack传送。
6、在主函数中重新创建GDT和IDT,初始化PIC后,开中断。

8、鼠标控制与32位模式切换相关推荐

  1. 第8天 鼠标控制与32位模式切换

    第8天 鼠标控制与32位模式切换 2020.4.2 1. 鼠标解读(1)(harib05a) 现在,我们让鼠标动起来. 先对bootpack.c中的HariMain函数进行修改. unsigned c ...

  2. 30天自制操作系统:第8天:鼠标控制与32位模式切换

    今天前半部分都是如何控制鼠标移动,将每次传送的三个字节处理成位置信息,最后指导鼠标指针移动. 后面的部分,是关于一段一直未讲解的汇编代码的讲解. 32位保护模式 书中用一连串汇编代码完成了从实模式进入 ...

  3. 30天自制操作系统——第八天鼠标控制与32位模式切换

    今天的任务是让鼠标真正移动起来,之前的路走的真是艰辛呀.终于到走到这里啦,下面正式开始了-- 鼠标解读(harib05a) 昨天我们已经能从鼠标取得数据了,接着要读取这些数据,看看鼠标是怎么移动的,在 ...

  4. 第8天:鼠标控制与32位模式切换

    8.1.鼠标解读 for (;;) {io_cli();if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {io_ ...

  5. 分享一款电机控制国产32位单片机MM32SPIN360C

    国产32位单片机MM32SPIN360C拥有M0内核的高性能32位微控制器,5V输出的LDO稳压器.三组具备有自举二极管的N通道半桥栅极驱动器.MCU最高工作频率可达96MHz,并内置SRAM高速存储 ...

  6. 相比32位, 64位的优势是什么?

    64 位和 32 位比较有哪些优势?  (1)如果说的是64 位宽 CPU,那么有 2 个优势: 可以执行更大数字的运算,这个优势在普通应用上不明显,但是对于数值计算较多的应用就非常明显. 64 位 ...

  7. Intel 64/x86_64/x86/IA-32处理器标志寄存器详解(4) - 32位EFLAGS - 状态标志与控制标志

    Status Flags 状态标志位(比特位0,2,4,6,7和11)指示了算术指令的结果,例如ADD,SUB,MUL,与DIV指令. 标志位 描述 CF(bit 0) 进位/借位Carry.如果算术 ...

  8. 计算机视觉课程第六讲-带你简单快速学习2021年春晚背后刘德华与背景分离切换到另一场景视觉算法(上集):OpenCV4鼠标控制图像和视频任意位置放大和缩小

    计算机视觉课程第六讲-带你简单快速学习2021年春晚背后刘德华与背景分离切换到另一场景视觉算法(上集):OpenCV4鼠标控制图像和视频任意位置放大和缩小 本专栏将会带大家学习 <计算机视觉与图 ...

  9. 一步一步学ROP之Android ARM 32位篇

    蒸米 · 2015/12/17 9:41 0x00 序 ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术,可以用来绕过现代操作系统的各种 ...

  10. 思科模拟器32位_三款另类的68k Mac模拟器

    之前说过两个主流的68k Mac模拟器,Mini vMac和BasiliskII.不过它们都没有真正的硬盘模拟,都是通过外置的软驱接口连接的"硬盘".那么这篇文章将介绍三款非主流的 ...

最新文章

  1. Linux磁盘配额(一)
  2. DataSource绑定DataTable.Select()显示system.data.DataRow问题解决的方法
  3. Unity协程(Coroutine)原理深入剖析再续
  4. oracle回滚事务的关键字,Oracle ROLLBACK语句(回滚事务)
  5. BIOS中的分区工具
  6. 我眼中的Visual Studio 2010架“.NET研究”构工具
  7. Linux文本处理(grep,sed)
  8. eclipse Dynamic web module相关问题
  9. mac 查看进程及杀进程
  10. 跳槽的5个误区,冷静一下
  11. Android ListView焦点事件冲突问题与解决
  12. Python中随机漫步的实现
  13. 亚马逊账号被关联能申诉得回来吗
  14. 聊下git merge --squash
  15. jquery实现新闻消息滚动
  16. 得到《三体》听书笔记
  17. web服务r oauth_通过OAuth访问社交网站,第3部分,将Web Twitter客户端部署到Google App Engine...
  18. Java小农养成记第四十天
  19. 有人用python抢到过吗_过年了,用Python抢到回家的车票,so easy!
  20. 七言.毕业12周年祭

热门文章

  1. 博科查看光功率_博科系交换机光模块信号强度查看
  2. win10怎么更新显卡驱动_win10系统AMD显卡驱动安装失败的解决方法
  3. qq出示测试软件语音聊天,腾讯qq语音聊天麦克风的[qq语音语音测试]解决方案
  4. 计算机综合应用技能,系统测评计算机综合应用技能期末作业题稿.doc
  5. R语言之导入数据源(二)
  6. 获取设备Mac地址和IP地址
  7. 设置Google连接burpsuite
  8. 安科瑞ACTB-6互感器二次侧开路保护装置
  9. twitter_关于Twitter和激进化的警告
  10. 斯坦福 计算机音乐 访问学者,韩宝强