[读书笔记]30 天自制操作系统 day8 鼠标控制与32位模式切换
来源:互联网 发布:福建顶点软件 垃圾 编辑:程序博客网 时间:2024/06/05 03:59
1. 鼠标解读
- 一个鼠标事件实际上会产生 3 个byte 的数据, 可以借助缓冲区
unsigned char mouse_dbuf[3]
, 对其数据进行输出显示 - 同时为了提高代码可读性, 采用
MOUSE_DEC
结构体对其进行封装 - 鼠标的三个字节数据保存在 buf[3] 中, 其中 buf[0] 的 低3 bit 表征鼠标的按键状态, buf[1], buf[2] 表征鼠标 x, y 的相对移动
- 鼠标移动代码:
void HariMain(void){ struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; char s[40], mcursor[256], keybuf[32], mousebuf[128]; int mx, my, i; struct MOUSE_DEC mdec; init_gdtidt(); init_pic(); io_sti(); /* IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 */ fifo8_init(&keyfifo, 32, keybuf); fifo8_init(&mousefifo, 128, mousebuf); io_out8(PIC0_IMR, 0xf9); /* PIC1とキーボードを許可(11111001) */ io_out8(PIC1_IMR, 0xef); /* マウスを許可(11101111) */ init_keyboard(); init_palette(); init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); mx = (binfo->scrnx - 16) / 2; /* 画面中央になるように座標計算 */ my = (binfo->scrny - 28 - 16) / 2; init_mouse_cursor8(mcursor, COL8_008484); putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16); sprintf(s, "(%3d, %3d)", mx, my); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); enable_mouse(&mdec); 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) { 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); /* マウス描く */ } } } }}
显示效果:
2. 通往32bit模式之路
- 这里主要分析一下 asmhead.nas 的一些内容
代码如下:
; haribote-os boot asm; TAB=4BOTPAK EQU 0x00280000 ; bootpackのロード先DSKCAC EQU 0x00100000 ; ディスクキャッシュの場所DSKCAC0 EQU 0x00008000 ; ディスクキャッシュの場所(リアルモード); 设定基本信息的存放地址CYLS EQU 0x0ff0 ; ブートセクタが設定するLEDS EQU 0x0ff1VMODE EQU 0x0ff2 ; 色数に関する情報。何ビットカラーか?SCRNX EQU 0x0ff4 ; 解像度のXSCRNY EQU 0x0ff6 ; 解像度のYVRAM EQU 0x0ff8 ; グラフィックバッファの開始番地 ORG 0xc200 ; このプログラムがどこに読み込まれるのか; 设定显卡的显示模式, 并将相应参数写入到内存的相应位置 MOV AL,0x13 ; VGAグラフィックス、320x200x8bitカラー MOV AH,0x00 INT 0x10 MOV BYTE [VMODE],8 ; 画面モードをメモする(C言語が参照する) MOV WORD [SCRNX],320 MOV WORD [SCRNY],200 MOV DWORD [VRAM],0x000a0000; 获取 BIOS 的LED 显示状态 MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],AL ; 设置 PIC 状态 MOV AL,0xff OUT 0x21,AL NOP ; OUT命令を連続させるとうまくいかない機種があるらしいので OUT 0xa1,AL CLI ; さらにCPUレベルでも割り込み禁止; 让 cpu 可以访问 1MB 以上的内存空间 CALL waitkbdout MOV AL,0xd1 OUT 0x64,AL CALL waitkbdout MOV AL,0xdf ; enable A20 OUT 0x60,AL CALL waitkbdout; 切换CPU 模式为 保护模式 [INSTRSET "i486p"] ; 486の命令まで使いたいという記述 LGDT [GDTR0] ; 暫定GDTを設定 MOV EAX,CR0 AND EAX,0x7fffffff ; bit31を0にする(ページング禁止のため) OR EAX,0x00000001 ; bit0を1にする(プロテクトモード移行のため) MOV CR0,EAX JMP pipelineflushpipelineflush: MOV AX,1*8 ; 読み書き可能セグメント32bit MOV DS,AX MOV ES,AX MOV FS,AX MOV GS,AX MOV SS,AX; 将 bootpack 的内容写入到 0x280000 位置处 MOV ESI,bootpack ; 転送元 MOV EDI,BOTPAK ; 転送先 MOV ECX,512*1024/4 CALL memcpy; 将各个部分(启动扇区, IPL)拷贝到1MB 内存后面 MOV ESI,0x7c00 ; 転送元 MOV EDI,DSKCAC ; 転送先 MOV ECX,512/4 CALL memcpy; 残り全部 MOV ESI,DSKCAC0+512 ; 転送元 MOV EDI,DSKCAC+512 ; 転送先 MOV ECX,0 MOV CL,BYTE [CYLS] IMUL ECX,512*18*2/4 ; シリンダ数からバイト数/4に変換 SUB ECX,512/4 ; IPLの分だけ差し引く CALL memcpy; asmheadでしなければいけないことは全部し終わったので、; あとはbootpackに任せる; bootpackの起動 MOV EBX,BOTPAK MOV ECX,[EBX+16] ADD ECX,3 ; ECX += 3; SHR ECX,2 ; ECX /= 4; JZ skip ; 転送するべきものがない MOV ESI,[EBX+20] ; 転送元 ADD ESI,EBX MOV EDI,[EBX+12] ; 転送先 CALL memcpyskip: MOV ESP,[EBX+12] ; スタック初期値 JMP DWORD 2*8:0x0000001bwaitkbdout: IN AL,0x64 AND AL,0x02 JNZ waitkbdout ; ANDの結果が0でなければwaitkbdoutへ RETmemcpy: MOV EAX,[ESI] ADD ESI,4 MOV [EDI],EAX ADD EDI,4 SUB ECX,1 JNZ memcpy ; 引き算した結果が0でなければmemcpyへ RET; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける ALIGNB 16GDT0: RESB 8 ; ヌルセレクタ DW 0xffff,0x0000,0x9200,0x00cf ; 読み書き可能セグメント32bit DW 0xffff,0x0000,0x9a28,0x0047 ; 実行可能セグメント32bit(bootpack用) DW 0GDTR0: DW 8*3-1 DD GDT0 ALIGNB 16bootpack:
- 基本流程
3. 内存分布图
4. 程序流程
下面我们来梳理下程序的运行流程
4.1 ipl10.nas
- 这部分主要负责先载入 启动扇区(0x7c00 ~ 0x7dff)
- 启动扇区载入完毕之后,将 IPL (软盘中除了启动扇区的那一块) 载入到 内存的 0x8200 ~ 0x34fff 区域(这里实际上只是载入了 10 个柱面 180kb)
- 跳转到 0xc200 处运行(这个地方实际就是 asmhead 的开始位置)
4.2 asmhead.nas
- 这部分的主要工作在之前已经提到过了
- 他将0x7c00 ~ 0x7dff 处的512byte 的启动扇区数据拷贝到 0x100000 处(1MB 空间开始位置)
- 然后将 0x8200 ~ 0x34fff 处的IPL 数据拷贝到 0x100200 处
- 同时, 将bootpack.hrb 的数据拷贝到0x280000位置处
- 同时跳转到 bootpack.hrb 处开始执行
4.3 bootpack.c
- 这部分实际就是我们 C 语言部分的操作, 用于处理键盘,鼠标中断响应, 图形绘制等操作
0 0
- [读书笔记]30 天自制操作系统 day8 鼠标控制与32位模式切换
- [读书笔记]30 天自制操作系统 day7 FIFO与鼠标控制
- 《30天自制操作系统》读书笔记Day8
- 鼠标控制与32位模式切换
- 30天自制操作系统day8
- 《30天自制操作系统》 day8 小结
- 8、鼠标控制与32位模式切换
- 08day 鼠标显示控制 与32位模式切换
- [读书笔记]30 天自制操作系统 day3 进入32bit模式并导入C语言
- 读书笔记《30天自制操作系统》day01
- 读书笔记《30天自制操作系统》day02
- 读书笔记《30天自制操作系统》day03
- 读书笔记《30天自制操作系统》day04
- 读书笔记《30天自制操作系统》day05
- 读书笔记《30天自制操作系统》day06
- 读书笔记《30天自制操作系统》day07
- 读书笔记《30天自制操作系统》day08
- 读书笔记《30天自制操作系统》day09
- java基础之Java变量命名规范 (转载)
- 同一个Controller里的同一个Service实例,在当前的Controller里的不同方法中状态不一致
- 第一篇博客哦
- kali linux上为GPU安装显卡驱动
- Linux下安装DB2数据库步骤
- [读书笔记]30 天自制操作系统 day8 鼠标控制与32位模式切换
- lombok的安装以及使用
- weex sdk集成到Android工程二. weex sdk集成到Android工程
- opencv中Mat介绍
- zookeeper系列之通信模型
- ATL中的CWindowImpl模板类
- 编译Caffe
- 关于WindowManager.LayoutParams包含的Window flag、softInputMode、changed系列变量的资料
- 高德定位,只能定位一次,导航图标就消失