六 vesa.inc 显卡绘图
[BITS 32]
[ORG 0x0000]
;JMP code
%macro GetXYAddr 2
XOR EAX,EAX
XOR EBX,EBX
XOR EDX,EDX
MOV AX,%2 ;第2个参数Ypos
MOV BX,%1 ;第1个参数Xpos
;坐标在显存中的计算方式Y*(屏幕宽度)+X/2
MOV CX,[SYSVAR+8]
MUL CX
MOV EDI,EDX ;进位
MOV CL,16
SHL EDI,CL
OR EDI,EAX ;积
ADD EDI,EBX
SHL EDI,1
MOV EAX,EDI
%endmacro
;------------------------------------------------------------------------------------------------
;计算色调5:5:5到5:6:5,以下是RGB颜色存放结构
;R DW 0;红色一个字
;G DW 0;绿色一个字
;B DW 0;蓝色一个字
;参数是2个字节
;-----------------------------------------------------------------------------------------------
RGB:
PUSH EBP ;保存IP返回内容
MOV EBP,ESP
XOR EBX,EBX
XOR EDX,EDX
XOR ECX,ECX
MOV AX,[ESP+0x0C] ;R第一个参数
MOV CL,32
DIV CL ;计算R/32
MOV BL,AH ;取莫(取余),把颜色值R放到EBX
MOV CL,6 ;每次移动6位
SHL BX,CL ;移动6位
MOV AX,[ESP+0x0A] ;G
MOV CL,64
DIV CL ;计算G
OR BL,AH ;取莫(取余),把颜色值G放到EBX
MOV CL,5 ;动5位
SHL BX,CL ;数据向左移动一个字节=8位
MOV AX,[ESP+0x08] ;B
MOV CL,32
DIV CL ;计算B
OR BL,AH ;取莫(取余),把颜色值B放到EBX
MOV AX,BX ;返回计算好的结果
MOV ESP,EBP
POP EBP
ret 0x6
;----------------------------------------------------------------------------------------------
;画点函数
;push WORD 是否使用双缓冲1使用0不使用
;push WORD color
;PUSH WORD y
;PUSH WORD x
;------------------------------------------------------------------------------------------------
SetPoint:
PUSH EBP
MOV EBP,ESP
XOR EAX,EAX
XOR EBX,EBX
XOR EDX,EDX
XOR ECX,ECX
XOR EDI,EDI
MOV AX,[ESP+0x0A] ;第三个参数Ypos
MOV BX,[ESP+0x08] ;第二个参数Xpos
;坐标在显存中的计算方式Y*(屏幕宽度)+X/2
MOV CX,[SYSVAR+8]
MUL CX
MOV EDI,EDX ;进位
MOV CL,16
SHL EDI,CL
OR EDI,EAX ;积
ADD EDI,EBX
;MOV CL,3
;SHR EDI,CL ;edi 除 8
SHL EDI,1
MOV EAX,EDI
MOV BX,[ESP+0x0C] ;第一个参数颜色
CMP [ESP+0x0E],WORD 1
JZ bo
MOV EDI,DWORD [DS:SYSVAR+0] ;SYSVAR+0 = 0xe0000000
MOV [DS:EDI+EAX],WORD BX
JMP sout
;先画到缓冲区然后复制到显示映射地址mmx以后再说
;以4字节方式移动
bo:
MOV EDI,DWORD VBE_FILP ;获得缓冲区地址
MOV [DS:EDI+EAX],WORD BX ;把计算好的颜色放到指定的坐标
sout:
MOV ESP,EBP
POP EBP
ret 0x8
;-------------------------------------------------------------------------------------
;获的指定像素点颜色
;PUSH WORD 1从缓冲区取0从显示映射内存取
;PUSH WORD y
;PUSH WORD x
;------------------------------------------------------------------------------------------------
GetPoint:
PUSH EBP
MOV EBP,ESP
XOR EAX,EAX
XOR EBX,EBX
XOR EDX,EDX
XOR ECX,ECX
XOR EDI,EDI
MOV AX,[ESP+0x0A] ;第2个参数Ypos
MOV BX,[ESP+0x08] ;第1个参数Xpos
;坐标在显存中的计算方式Y*(屏幕宽度)+X/2
MOV CX,[SYSVAR+8]
MUL CX
MOV EDI,EDX ;进位
MOV CL,16
SHL EDI,CL
OR EDI,EAX ;积
ADD EDI,EBX
;MOV CL,3
;SHR EDI,CL ;edi 除 8
SHL EDI,1
MOV EAX,EDI
CMP [ESP+0x0C],WORD 1
JZ vm
MOV EDI,DWORD [DS:SYSVAR+0] ;SYSVAR+0 = 0xe0000000
MOV AX,[DS:EDI+EAX]
JMP gout
vm:
MOV EDI,DWORD VBE_FILP ;获得缓冲区地址
MOV AX,[DS:EDI+EAX] ;把计算好的颜色放到指定的坐标
gout:
MOV ESP,EBP
POP EBP
ret 0x6
;--------------------------------------------------------------------------------------
;PUSH WORD 1使用缓冲区0不使用缓冲区
;PUSH WORD starty
;PUSH WORD startx
;PUSH WORD endy
;PUSH WORD endx
;PUSH WORD COLOR
;绘制一个指定区域的方块
;----------------------------------------------------------------------------------------------
DrawBox:
PUSH EBP
MOV EBP,ESP
SUB ESP,4 ;开遍2个2字节变量
XOR EBX,EBX
XOR EDX,EDX
XOR EAX,EAX
MOV DX,[ESP+14+4] ;x
MOV BX,[ESP+16+4] ;y
MOV [ESP+0],DX ;保存x
MOV [ESP+2],BX ;保存y
x:
MOV BX,[ESP+16+4]
MOV [ESP+2],BX
y:
PUSH WORD [ESP+18+4];缓冲模式
PUSH WORD [ESP+8+6] ;颜色
PUSH WORD [ESP+2+4] ;y
PUSH WORD [ESP+0+6] ;x
CALL SetPoint
ADD [ESP+2],WORD 1 ;y++
MOV BX,[ESP+2]
CMP BX,[ESP+12+4]
jnz y
ADD [ESP+0],WORD 1 ;x++
MOV BX,[ESP+0]
CMP BX,[ESP+10+4]
jnz x
CMP [ESP+18+4],WORD 0
JZ bxout
push word 0 ;0=常规拷贝,1=与目标or,2=与目标and,3=与目标xor
push word [ESP+16+6] ;dy
push word [ESP+14+8] ;dx
push word [ESP+12+10] ;endy
push word [ESP+10+12] ;endx
push word [ESP+16+14] ;starty
push word [ESP+14+16] ;startx
CALL BitBlt
bxout:
MOV ESP,EBP
POP EBP
ret 0x0C
;---------------------------------------------------------------------------------
;重绘指定大小的区域
;PUSH WORD starty
;PUSH WORD startx
;PUSH WORD endy
;PUSH WORD endx
;这个函数实现强制刷新区域
;通过指定的区域进行刷新,建立消息系统以后会发送这个消息到所有的窗体
;包括桌面如果这些窗体的某个部分存在于这个刷新范围内那么刷新
;----------------------------------------------------------------------------------------------
RefreshRect:
PUSH EBP
MOV EBP,ESP
SUB ESP,4 ;开遍2个6字节变量
XOR EBX,EBX
XOR EAX,EAX
MOV AX,[ESP+12+4] ;x
MOV BX,[ESP+14+4] ;y
MOV [ESP+0],AX ;保存x
MOV [ESP+2],BX ;保存y
rx:
MOV BX,[ESP+2]
MOV [ESP+14+4],BX
ry:
PUSH WORD 1
PUSH WORD 0 ;需要计算颜色
PUSH WORD [ESP+14+4+4] ;y
PUSH WORD [ESP+12+4+6] ;x
CALL SetPoint
ADD [ESP+14+4],WORD 1 ;y++
MOV BX,[ESP+14+4]
CMP BX,WORD [ESP+10+4]
jnz ry
ADD [ESP+12+4],WORD 1 ;x++
MOV BX,[ESP+12+4]
CMP BX,WORD [ESP+8+4]
jnz rx
push word 0 ;0=常规拷贝,1=与目标or,2=与目标and,3=与目标xor
push word [ESP+16+6] ;dy
push word [ESP+14+8] ;dx
push word [ESP+12+10] ;endy
push word [ESP+10+12] ;endx
push word [ESP+16+14] ;starty
push word [ESP+14+16] ;startx
CALL BitBlt
MOV ESP,EBP
POP EBP
ret 0x08
;------------------------------------------------------------------------------------
;DrawPixelBuf显示颜色点阵
;PUSH DWORD 缓冲区地址
;PUSH WORD 缓冲区大小
;PUSH WORD matrix_width/endy
;PUSH WORD matrix_height/endx
;PUSH WORD starty
;PUSH WORD startx
;从startx,starty点开始画横向endx个点从向endy个点的矩阵
;通过startx,starty把从缓冲区地址拿出来的像素颜色送到相应的
;显卡映射地址
;--------------------------------------------------------------------------------------
DrawPixelBuf:
PUSH EBP
MOV EBP,ESP
SUB ESP,4 ;申请局部变量
;先实现单2字节移动也就是一次移动一个像素点.以后再说mmx移动
XOR EAX,EAX
XOR EBX,EBX
MOV AX,[ESP+8+4] ;startx
MOV [ESP+0],AX ;startx放到局部变量
MOV BX,[ESP+10+4] ;starty
MOV [ESP+2],BX ;starty放到局部变量
ADD [ESP+12+4],AX ;endx
ADD [ESP+14+4],BX ;endy
;[ESP+16+4] ;缓冲区大小-字节
MOV ESI,[ESP+18+4] ;缓冲区地址
py:
MOV BX,[ESP+8+4]
MOV [ESP+0],BX ;初始化x再次循环
px:
MOV AX,[DS:ESI]
XOR AL,0x11 ;如果是需要挖掉的颜色0x1111那么不显示
JZ ..@mask
XOR AL,0x11 ;如果不是需要挖掉的颜色0x1111那么恢复
PUSH WORD 0
PUSH AX
PUSH WORD [ESP+2+4];y
PUSH WORD [ESP+0+6];x
CALL SetPoint
..@mask:
ADD ESI,2
ADD [ESP+0],WORD 1
MOV BX,[ESP+0]
CMP [ESP+12+4],BX
JNZ px
ADD [ESP+2],WORD 1
MOV BX,[ESP+2]
CMP [ESP+14+4],BX
JNZ py
;push word 0 ;0=常规拷贝,1=与目标or,2=与目标and,3=与目标xor
;push word [ESP+10+4] ;dy
;push word [ESP+8+4] ;dx
;push word [ESP+14+4] ;endy
;push word [ESP+12+4] ;endx
;push word [ESP+10+4] ;starty
;push word [ESP+8+4] ;startx
;CALL BitBlt
MOV ESP,EBP
POP EBP
ret 0x0E
;--------------------------------------------------------------------------
;BitBlt类似windows的GDI函数
;push word 0=常规拷贝,1=与目标or,2=与目标and,3=与目标xor
;push word dy
;push word dx
;push word endy
;push word endx
;push word starty
;push word startx
;----------------------------------------------------------------------------
BitBlt:
PUSH EBP
MOV EBP,ESP
SUB ESP,8
XOR EAX,EAX
XOR EBX,EBX
MOV AX,[ESP+8+8] ;x
MOV BX,[ESP+10+8] ;y
MOV [ESP+0],AX ;x
MOV [ESP+2],BX ;y
MOV AX,[ESP+16+8] ;dx
MOV BX,[ESP+18+8] ;dy
MOV [ESP+4],AX ;dx
MOV [ESP+6],BX
;[ESP+12+8] endx
;[ESP+14+8] endy
;[ESP+16+8] dx
;[ESP+18+8] dy
;[ESP+20+8] 0/1/2/3
memy:
MOV BX,[ESP+8+8]
MOV [ESP+0],BX ;恢复x坐标从新计数
MOV BX,[ESP+16+8]
MOV [ESP+4],BX
memx:
CMP [ESP+20+8],WORD 0 ;常规操作
JZ j0
CMP [ESP+20+8],WORD 1 ;or
JZ j1
CMP [ESP+20+8],WORD 2 ;and
JZ j2
CMP [ESP+20+8],WORD 3 ;xor
JZ j3
j0:JMP non0
j1:JMP or1
j2:JMP and2
j3:JMP xor3
non0:
GetXYAddr [ESP+0],[ESP+2] ;x,y,ret=eax
MOV EDI,VBE_FILP ;获得缓冲区地址
MOV ESI,[DS:EDI+EAX] ;把计算好的颜色放到指定的坐标
GetXYAddr [ESP+4],[ESP+6]
MOV EDI,DWORD [DS:SYSVAR+0] ;SYSVAR+0 = 0xe0000000
MOV [DS:EDI+EAX],SI ;从缓冲区取得的颜色放到指定坐标的显示内存
or1:
and2:
xor3:
ADD [ESP+0],WORD 1 ;x++
ADD [ESP+4],WORD 1;目标x坐标累加
MOV BX,[ESP+0]
CMP BX,[ESP+12+8]
JZ gmmy
JMP memx
gmmy:
ADD [ESP+2],WORD 1
ADD [ESP+6],WORD 1 ;目标y坐标累加
MOV BX,[ESP+2]
CMP BX,[ESP+14+8]
JZ mmout
JMP memy
mmout:
MOV ESP,EBP
POP EBP
ret 0x0E
;汉字显示根据内存地址显示,汉字点阵16*16=32字节点阵
;PUSH WORD 汉字编码0xB0A1开始
;PUSH WORD 颜色
;PUSH WORD 是否使用背景颜色0不使用1使用
;PUSH WORD 背景颜色
;PUSH WORD 1是与背景求反色0不求反色
;PUSH WORD y坐标
;PUSH WORD x坐标
DrawText:
PUSH EBP
MOV EBP,ESP
XOR EAX,EAX
XOR EDX,EDX
XOR ESI,ESI
SUB ESP,8
;a0a0编码开始
MOV AL,[ESP+21+8] ;取区码
MOV CL,0xA0
SUB Al,CL ;b0-a0计算区
MOV CL,94 ;区码*94
MUL CL
MOV EDX,EAX
XOR EAX,EAX
MOV AL,[ESP+20+8] ;取位码
MOV CL,0xA0
SUB AL,CL ;计算区内的第几个汉字
ADD EDX,EAX ;区码和位码相加
MOV EAX,EDX ;把计算好的区位码送到EAX
XOR EDX,EDX
MOV CX,32 ;计算地址
MUL CX
MOV ESI,EDX ;进位
MOV CX,16
SHL ESI,CL
OR ESI,EAX
SUB ESI,0xBE0 ;调整到b040到第一个汉字啊
ADD ESI,FontLibrary ;取字库地址+偏移
MOV AX,[ESP+8+8]
MOV DX,[ESP+10+8]
MOV [ESP+2],AX ;x
MOV [ESP+4],DX ;y
MOV [ESP+0],WORD 0 ;清空变量
hlop:
MOV AL,[DS:ESI] ;获得点阵
MOV ECX,8
hi8:
PUSH CX
SHL AL,1
PUSH AX
JNC backg
;画点
PUSH WORD 1 ;使用双缓冲
PUSH WORD [ESP+18+14] ;颜色
PUSH WORD [ESP+10+16] ;y
PUSH WORD [ESP+8+18] ;x
CALL SetPoint
JMP nobg
backg:
CMP [ESP+16+12],WORD 0 ;是否使用背景
JZ nobg
PUSH WORD 1 ;使用双缓冲
PUSH WORD [ESP+14+14] ;背景颜色
PUSH WORD [ESP+10+16] ;y
PUSH WORD [ESP+8+18] ;x
CALL SetPoint
nobg:
POP AX
POP CX
ADD [ESP+8+8],WORD 1 ;x坐标+1
LOOP hi8
INC ESI ;下一个8位点阵
MOV AL,[DS:ESI] ;获得点阵
MOV ECX,8
hi16:
PUSH CX
SHL AL,1
PUSH AX
JNC backg1
;画点
PUSH WORD 1 ;使用双缓冲
PUSH WORD [ESP+18+14] ;颜色
PUSH WORD [ESP+10+16] ;y
PUSH WORD [ESP+8+18] ;x
CALL SetPoint
JMP nobg1
backg1:
CMP [ESP+16+12],WORD 0 ;是否使用背景
JZ nobg1
PUSH WORD 1 ;使用双缓冲
PUSH WORD [ESP+14+14] ;背景颜色
PUSH WORD [ESP+10+16] ;y
PUSH WORD [ESP+8+18] ;x
CALL SetPoint
nobg1:
POP AX
POP CX
ADD [ESP+8+8],WORD 1 ;x坐标+1
LOOP hi16
SUB [ESP+8+8],WORD 16
ADD [ESP+10+8],WORD 1 ;y+1
INC ESI ;下一个8位点阵
ADD [ESP+0],WORD 1
CMP [ESP+0],WORD 16
JZ rout
JMP hlop
rout:
MOV AX,[ESP+4] ;y
MOV BX,[ESP+2] ;x
push WORD 0;0=常规拷贝,1=与目标or,2=与目标and,3=与目标xor
push WORD AX;dy
push WORD BX;dx
ADD AX,16
ADD BX,16
push AX ;endy
push BX ;endx
push WORD [ESP+4+10];starty
push WORD [ESP+2+12];startx
CALL BitBlt
MOV ESP,EBP
POP EBP
ret 0x0E