四、mouse.inc 鼠标驱动部分(设置鼠标中断,建立中断处理程序)
[BITS 32]
[ORG 0x0]
;鼠标中断处理程序
INT_MOUSE:
PUSHAD
PUSHF
;刷新鼠标所在区域
ReadPort 0x60
MOV AH,0
CMP [DS:SYSVAR+0x10],BYTE 0
JZ c0
CMP [DS:SYSVAR+0x10],BYTE 1
JZ c1
CMP [DS:SYSVAR+0x10],BYTE 2
JZ c2
c0:
jmp button
c1:
jmp xpos
c2:
jmp ypos
button:
TEST AL,0x1 ;1=leftbutton 2=rightbutton
JZ bt0
bt0:
MOV [DS:SYSVAR+0x11],BYTE AL ;鼠标按键给变量
ADD [DS:SYSVAR+0x10],BYTE 1 ;读取累加器+1
JMP rt ;处理完毕跳走
xpos:
ADD [DS:SYSVAR+0x10],BYTE 1 ;读取累加器+1
;计算符号加减
CBW
MOV [DS:SYSVAR+0x12],WORD AX ;x坐标放到零时变量
MOV AX,[DS:SYSVAR+0x0C] ;读出坐标变量内容与鼠标移动偏移相加
ADD AX,[DS:SYSVAR+0x12] ;x坐标+移动偏移
MOV [DS:SYSVAR+0x12],WORD 0 ;清空临时变量
CMP AX,0xf9ff
JNG x1
MOV [DS:SYSVAR+0x0C],WORD 0xF9FF
JMP x2
x1:
CMP AX,0xFA00
JNG x2
MOV [DS:SYSVAR+0x0C],WORD 0xFA00
x2:
MOV [DS:SYSVAR+0x0C],WORD AX ;累加坐标放到坐标变量中
JMP rt ;处理完毕跳走
ypos:
MOV [DS:SYSVAR+0x10],BYTE 0 ;清零读取累加器
CBW
;ADD [DS:SYSVAR+0x10],BYTE 1 ;读取累加器+1
;SHR AL,1
NEG AX
MOV [DS:SYSVAR+0x12],WORD AX ;y坐标放到零时变量
MOV AX,[DS:SYSVAR+0x0E] ;读出坐标变量内容与鼠标移动偏移相加
ADD AX,[DS:SYSVAR+0x12] ;y坐标+移动偏移
MOV [DS:SYSVAR+0x12],WORD 0 ;清空临时变量
CMP AX,32767
JNG y1
MOV [DS:SYSVAR+0x0E],WORD 0
JMP y2
y1:
CMP AX,598
JNG y2
MOV [DS:SYSVAR+0x0E],WORD 598
y2:
MOV [DS:SYSVAR+0x0E],WORD AX ;累加坐标放到坐标变量中
;保存鼠标将要显示的区域
; PUSH WORD 8
; PUSH WORD 8
; PUSH WORD [DS:SYSVAR+0x0E];y
; PUSH WORD [DS:SYSVAR+0x0C];x
; CALL GetCurLastRect
;区域恢复
; PUSH DWORD SYSMOUSEBUF
; PUSH WORD 0x80
; PUSH WORD 8
; PUSH WORD 8
; PUSH WORD [DS:SYSVAR+0x16];y
; PUSH WORD [DS:SYSVAR+0x14];x
; CALL DrawPixelBuf
push word 0 ;0=常规拷贝,1=与目标or,2=与目标and,3=与目标xor
PUSH WORD [DS:SYSVAR+0x16];endy
PUSH WORD [DS:SYSVAR+0x14];endx
MOV AX,[DS:SYSVAR+0x16];endy
MOV BX,[DS:SYSVAR+0x14];endx
ADD AX,8
ADD BX,8
PUSH AX
PUSH BX
PUSH WORD [DS:SYSVAR+0x16];starty
PUSH WORD [DS:SYSVAR+0x14];startx
CALL BitBlt
;显示鼠标光标
PUSH DWORD SYSMOUSEBUF+0x80;鼠标像素所在位置
PUSH WORD 0x80
PUSH WORD 8
PUSH WORD 8
PUSH WORD [DS:SYSVAR+0x0E];y
PUSH WORD [DS:SYSVAR+0x0C];x
CALL DrawPixelBuf
MOV AX,[DS:SYSVAR+0x0E];y
MOV BX,[DS:SYSVAR+0x0C];x
MOV [DS:SYSVAR+0x16],AX;y
MOV [DS:SYSVAR+0x14],BX;x
JMP rt
rt:
MOV AL,0x20
OUT 0x20,AL
OUT 0xA0,AL
POPF
POPAD
IRET
;----------------------------------------------------------------------------
;通过点阵信息生成一个16位色的像素点阵
;鼠标指针是个8*8位的点阵也就是8个子节
;0x4000-0x40ff ;鼠标指针数据256byte
;----------------------------------------------------------------------------
SetCursorColor:
PUSH EBP
MOV EBP,ESP
SUB ESP,2 ;开辟局部变量
MOV ESI,0x4000
MOV EDI,0x4080
cursor:
MOV BL,[DS:ESI]
MOV ECX,8
MOV [ESP+0],WORD 1 ;指针轮廓开关
lopshl:
PUSH CX
SHL BL,1
JC matrix ;CF是否溢出是否有点阵数据
MOV AX,[ESP+0+2] ;获得绘制开关-0xffff表示矩阵开始
CMP AX,2
JNZ nomatrix ;如果指针矩阵还没有开始
MOV [DS:EDI],WORD 0xFFFF ;鼠标轮廓内部用白色填充
JMP goon
nomatrix: ;处理鼠标光标影响没处理时的空点阵
MOV [DS:EDI],WORD 0x1111 ;光标外形以外的部分不显示.也就是把鼠标光标的形状挖出来
JMP goon
matrix:
ADD [ESP+0+2],WORD 1 ;如果有点阵那么标志设置1表示点阵开始
MOV [DS:EDI],WORD 0x0000 ;鼠标轮廓用黑色
goon:
ADD EDI,2
POP CX
LOOP lopshl
INC SI
CMP SI,0x4008
JNZ cursor
;保存鼠标将要显示的区域
PUSH WORD 8
PUSH WORD 8
PUSH WORD [DS:SYSVAR+0x0E];y
PUSH WORD [DS:SYSVAR+0x0C];x
CALL GetCurLastRect
MOV ESP,EBP
POP EBP
ret
;---------------------------------------------------------------------------
;获得指定区域的像素
;并保存到鼠标指针的第一个128b的缓冲区
;PUSH WORD matrix_y
;PUSH WORD matrix_x
;PUSH WORD starty
;PUSH WORD startx
;--------------------------------------------------------------------------
GetCurLastRect:
PUSH EBP
MOV EBP,ESP
SUB ESP,4
XOR EAX,EAX
XOR EBX,EBX
MOV AX,[ESP+8+4] ;x
MOV BX,[ESP+10+4] ;y
MOV [ESP+0],AX
MOV [ESP+2],BX
ADD [ESP+12+4],AX ;计算endx
ADD [ESP+14+4],BX ;计算endy
MOV EDI,SYSMOUSEBUF ;鼠标指针缓冲区地址
my:
MOV BX,[ESP+10+4]
MOV [ESP+2],BX ;重置x坐标
mx:
PUSH EDI
PUSH WORD 1 ;从缓冲区取
PUSH WORD [ESP+2+6] ;y
PUSH WORD [ESP+0+8] ;x
CALL GetPoint
POP EDI
MOV [DS:EDI],AX
ADD EDI,2
ADD [ESP+2],WORD 1
MOV BX,[ESP+2]
CMP BX,[ESP+14+4]
JNZ mx
ADD [ESP+0],WORD 1
MOV BX,[ESP+0]
CMP BX,[ESP+12+4]
JNZ my
MOV ESP,EBP
POP EBP
ret 0x8
;初始化鼠标中断
InitMouse:
PUSH EBP
MOV EBP,ESP
;设置中断表项地址
MOV EAX,INT_MOUSE
MOV CL,16
MOV [DS:SYSTB+0x3C*8],WORD AX
SHR EAX,CL
PUSH CS
POP CX
MOV [DS:SYSTB+2+0x3C*8],WORD CX
MOV [DS:SYSTB+6+0x3C*8],WORD AX
CLI
XOR EDX,EDX
XOR EAX,EAX
MOV DX,0xA1
IN AL,DX
AND AL,11101111b ;打开鼠标中断
OUT DX,AL
;对 8042 键盘控制芯片进行编程
mov bl,0xa8 ; enable mouse cmd
call kb_cmd
call kb_read ; read status
mov bl,0x20 ; get command byte
call kb_cmd
call kb_read
or al,3 ; enable interrupt
mov bl,0x60 ; write command
push eax
call kb_cmd
pop eax
call kb_write
mov bl,0xd4 ; for mouse
call kb_cmd
mov al,0xf4 ; enable mouse device
call kb_write
call kb_read ; read status return
STI
MOV ESP,EBP
POP EBP
ret