[第8天] 鼠标控制

      其实现在已经第10天也已经完成。但是只记录到第8天,这不太好啊。第8天,作者讲了怎么控制鼠标以及填了GDT这个坑。总体来说还是轻松简单的,因为GDT基本在之前搞明白了。

鼠标数据:

      鼠标初始化之后,会传送一个字节”FA”。当接受到这个字节后就表示鼠标已经准备好了。在这之后鼠标的数据都是3个字节一组,但是会分3次传送。所以要处理这3个阶段。这3个字节有各自的意义。见OSDev。鼠标还可以进行一些设置, 我直接按作者的来,没有进行其他测试。

Y overflowX overflowY sign bitX sign bitAlways 1Middle BtnRight BtnLeft Btn
X movement
Y movement

数据解读:

      既然得到了鼠标的数据,就要对其进行处理。首要目的就是能移动鼠标。就要获取鼠标的位置。根据第2字节和第3字节就可以知道移动情况。但是Y的移动方向相反,要处理如下:(然后通过 mx += mdec.x; my += mdec.y; 就可以更新鼠标位置)

鼠标移动:

      在这里,鼠标移动还很简单,只要重新绘制鼠标的图像就好了,详细见github。因此也有不足的地方,就是会覆盖图层,如下图所示。这个问题,在第10天解决。姑且就放着不管。

mouse-move
Mouse Move With Error

32位解读:

      作者在这天解释了gdt的载入和程序的跳转。以及作者系统的内存分布。作者的系统从0x00280000开始,我从0xc400开始。但是我以后应该也会往后移。所以来用bochs来看一下gdtr吧。首先bochs指示gdtr在内存0x270000的位置,大小为0xffff。

gdtr-idtr
gdtr in bochs

      所以看看0x00270000位置的内存放着什么吧。因为我只定义了2个gdt,外加一个空gdt,所以一共3个记录。截图显示无误。早发现bochs,我估计我已经到13天了。

gdtr0x270000
0x270000 GDT

注意:

      作者介绍的是PS2鼠标,虽然说USB鼠标模拟了PS2,但在处理上还是存在一定差别,因为在真机上鼠标处理会有问题。鼠标的反映会不正常。

 链接:

  1. bochs debugger

[第7天] 键盘 FIFO缓冲和bochs

       今天最大的收获是从qemu转向bochs。不是说qemu不好,而是bochs专业,可以debug,是制作操作系统必备啊!qemu是稳定,是为真正的操作系统准备的。真是相见恨晚,虽然之前听说过bochs,而且我也查过qemu怎么dump memory,为什么就没有发现bochs自带这个功能。。现在亡羊补牢,再也不用手动判断内存中的内容了。。苦水吐不完啊,当时GDT折腾的时候,二分法找内存对应位置的值,想想我真是太机智了,根据HLT之后CPU占有率来判断,那个内存是不是测试的值。

       然后今天主要是讲了获取键盘按键编码和缓冲。然后顺便打开了鼠标的开关。主要内容是FIFO缓冲,这个学过编程就是小意思啊。

Bochs准备:

       由于Arch自带的bochs没有gui,所以还得手动编译。根据osdev,configure一下就可以make了。最后会出个问题,就是libgui.a(gtk_enh_dbg_osdep.o): undefined reference to symbol ‘pthread_create@@GLIBC_2.2.5’。 原因是Makefile某个地方没有加-lpthread。容易解决。编译好了之后先要配置。

  1. 准备硬盘文件。使用bximage命令即可。我创建了1个1024mb的。要记下配置。
  2. bochsrc,这就是启动bochs的配置文件。根据Search Order,选择一个合适的位置。我的配置文件如下:
  3. bximage

  4. 然后就可以启动了。bochs -q。bochs

按键处理:

       感觉这个没有什么要特别注意的地方。就是处理中断后,把数据获取。由于不能让CPU被中断处理打断,一般都要将获取的值缓冲起来,然后内核主程序循环查看缓冲区是否有新数据。这就引发了下面的内容。FIFO。

FIFO:

       作者还是使用最简单的方法实现了FIFO,我也就不管了,跟着照做。具体代码见github

使能鼠标:

       鼠标由于各种原因,需要两步才能启用。具体原理我也不是很明白,我觉得这不是重点,所以就快速通过。下图1E是按下A松开的按键编码,00是获取的鼠标数据。

keyboard and mouse

链接:

  1. bochsrc
  2. bochs hacking guide

[第6天] 中断

 坑爹的一周终于过去了,今天去考了所谓的java证书,一天学习的东西还能应付应付。但是那考卷质量不行,估计这结果也是可以是水水过的。所以一有时间,我就开始第六天。毕竟我的目标是学习linux,要抓紧时间,先实现一个自己的。今天也把GDT大概搞清楚了。而且今天学了键盘的中断,感觉还是蛮好的。虽然掉进一个坑。

分割文件:

 kernel.c文件太大了,必须分开处理。现在的分割为4个,如下:

  1. graphic.c: 处理图像绘制,界面等
  2. init.c: kernel入口
  3. dsctbl.c: GDT和IDT初始化
  4. int.c: 中断设置

  Makefile用通配符,可以同时编译依赖关系,免得写上一大坨。还学到了ld -r选项,relocatable,就可以把这些.o文件都重新整合起来。所以代码还是见github

GDT理解:

 感觉今天最大的收获,是搞明白了GDT。原本以为GDT会影响代码的跳转,后来看看资料,发现GDT的作用就是分割内存,保护系统和机器。CS,SS等寄存器不影响代码的执行和跳转。我现在实现的还只是Flat Setup,就是系统代码段使用32bits地址空间,系统数据段也是使用全部内存。这当然不能实现数据隔离,但是目前我还没有真正区别开数据和代码,所以先这样不管。能运行就好。GDT的意义如下:

580px-SegmentDescriptor.svg

 要注意的是,Base是分成3块的。还有G,DB,A各种意义,可以直接网上找。要注意这只是一条GDT。可以设置很多记录。当然进入保护模式,必不可少的有3个记录。Null Segment,Code Segment,Data Segment。Null是保留的,无意义,起始位置是0x00,Code Segment为0x08,Data Segment为0x10,因为每个有8 bytes。以此类推下去。当要跳转时, jmp CODE_SEG:init_pm ,CODE_SEG就是0x8。CPU就会自动将该地址描述的GDT内容读入。大概是这样,估计还有点理解错误。还有IDT,没去搞。

中断处理:

 中断处理,先要初始化PIC,我就直接抄代码,跳过了。直接IRQ,IRQ是指Interrupt Request。用INT 0x20-INT 0x2f,接收IRQ0~15, (因为INT 0x1f之前是CPU自己用的)。鼠标对应的中断是IRQ12,键盘是IRQ1,因此要处理INT 0x2c和INT 0x21。先要注册中断处理程序。其中_asm_inthandler是用汇编写的处理程序。1*8 指第一块GDT,我就傻逼了。作者用的是2*8,因为作者把第二块当作代码段,不按常理出牌啊!害我搞了半天。中断发生后总是会自动重启。因为这用的是数据段,不能执行。所以CPU启动了保护机制。

 说是使用_asm_inthandler处理,其实是在中间CALL了C写的函数。比如INT 0x21的真正出来函数为:

 最后的键盘中断,鼠标还没有完成,要到下一天。

SlefMouse

链接:

  1. Makeflie ld
  2. GDT and IDT