NASM 纯汇编打造简单中文操作系统(6 vesa.inc 显卡绘图)

 

六 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

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

替计划实验室Plan T Labs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值