說明:這裏只介紹使用點陣字庫。
準備工作:
1、首先必須創建相應的點陣信息
我們來創建壹個16×16的兩個漢字的點陣,其實很簡單,妳在紙上畫壹個行列
各有16個格子的方塊出來,然後按其大小,在裏面寫壹個字,比如”成“,建
議妳寫得粗壹點,這時妳會發現有些格子中被字的筆畫穿過,有的仍是空格
子,現在妳把沒有筆畫穿過的記為0,有筆畫的記為1,從第壹行開始,將這個
16×16的“點陣”的信息記下來,由於每行有16個位,所以需要2個字節來記錄壹
行,***16行,所以***需2×16=32個字節來保存壹個字的“點陣”.
比如:漢-->00000h,04008h,037fch,01008h,08208h,06208h,02210h,00910h
01120h,020A0h,0E040h,020A0h,02110h,02208h,0240Eh,00804h
當然我這個“點陣”是從別的字庫裏載取出來的,但上面的方法絕對是可行的
點陣本質上就是這樣生成的。
2、編寫壹個顯示壹個像素的子程序
面臨的任務:在圖形模式下,在屏幕上打印壹個像素點
分析:
所需的變量:初始的左上角的坐標值x0,y0
默認參數: 默認分辨率為640×480×16色模式
(因為這是VGA標準BIOS支持的模式)
默認顏色為黑底黃字
實現:(參考了《VGA實用編程技術》羅健軍 清華大學出版社 1995)
;功能:
; 在指定的屏幕位置用指定的顏色畫壹個點
;入口參數:
; bx = x0 象素在屏幕上的X坐標
; ax = y0 象素在屏幕上的Y坐標
; cl = color 象素的顏色值
writePix proc
linelen = 80 ;640*480*16色模式下壹條掃描線占用的字節數
;=Width/8
;計算象素點的位置
push es
push bp
push dx
push ax
push di
push cx
push bx
mov bp,sp
mov cl,3
shr bx,cl ;X0/8
mov cx,linelen
mul cx
add ax,bx ;至此ax中為像素點的偏移,dx為頁號
mov di,ax
;設置映象屏蔽寄存器
mov dx,sequen_ctl
mov al,2
out dx,al
inc dx
mov al,0fh ;四個位面全部充許寫
out dx,al
;選擇寫方式2
mov dx,graphi_ctl
mov al,5
out dx,al
inc dx
mov al,2
out dx,al
;計算屏蔽碼,並設置位屏蔽寄存器
dec dx
mov al,8
out dx,al
mov cx,[bp] ;取出X坐標
and cl,7
mov al,80h
shr al,cl
inc dx
out dx,al
;寫數據
mov ax,vgaseg ;ES段指向顯存地址0a000h
mov es,ax
mov ax,[bp+2] ;取顏色值
mov ah,es:[di] ;讀壹次使屏蔽寄存器有效
mov es:[di],al ;寫入顯示存儲器
pop bx
pop cx
pop di
pop ax
pop dx
pop bp
pop es
ret
writePix endp
3、編寫壹個輸出壹個漢字圖形字符的子程序,有了2的基礎這壹步顯得比較容易,實現
如下:
;在圖形模式下顯示壹個漢字
;輸入參數:
; BX=x0 初始左上角X坐標
; AX=y0 初始左上角Y坐標
; CX=color 其實只是cl表示顏色
; ds:si=buff 字符點陣信息首地址
;返回值:無
DispZhC proc
push si
push bp
push ax
push bx
push cx
push dx
mov bp,sp
xor dx,dx ;dx 當前行
jmp a1
Disp:
inc si
inc si ;指向下壹個字
inc dx ;行記數加壹
a1:
cmp dx,16 ;當前行為0-15,因為是16*16點陣
je Done
xor cx,cx ;cx 當前列初始化
mov bx,word ptr [si] ;讀入壹行的點陣信息,壹行兩個字節表示
DispL:
cmp cx,16
je Disp ;換行
or cx,cx ;清零CF
shl bx,1
jc DispP ;如果當前位是1,顯示壹個點
inc cx
jmp DispL
DispP:
push ax
push bx
push cx
mov ax,[bp+6]
add ax,dx
mov bx,[bp+4]
add bx,cx
mov cx,[bp+2] ;顏色值在cl中
call writePix
pop cx
inc cx
pop bx
pop ax
jmp DispL
Done:
pop dx
pop cx
pop bx
pop ax
pop bp
pop si
ret
DispZhC endp
4、編寫壹個輸出壹個字符串的子程序
面臨的任務:妳已經擁有顯示壹個字符的子程序,現在要對它連續調用,完整
地顯示緩沖區中的全部漢字點陣。
分析:
所需的變量:整個字符串初始的左上角坐標x0,y0
字符串長度
在顯示每個字符時傳遞給子程序的左上角坐標x1,y1
默認參數: 默認為16點陣
默認字間距為5個像素
程序主要結構:
壹個單重循環,按字符串長度進行循環。
我的實現:
;在圖形模式下顯示指定長度的字符串
;輸入參數:
; ds:si 字符串點陣緩沖區的首地址
; ax=y0 字符串第壹個字符左上角的Y坐標
; bx=x0 字符串第壹個字符左上角的X坐標
; ch=n
; cl=color
;返回值:無
DefDis = 5 ;每兩個符號間的默認間距為5個像素
CharWidth = 16 ;默認為16點陣,這也是每個字符的像素寬度
DispZhS proc
push bp
push ax
push bx
push ds
push si
push cx
push dx
mov bp,sp
xor dx,dx
jmp s1
nextChar: ;指向下壹個要輸出的字符
add si,32
add bx,DefDis+CharWidth
s1:
cmp dh,ch ;是否已經輸出了指定個數的字符
je Dones
call DispZhc
inc dh
jmp nextChar
Dones:
pop dx
pop cx
pop si
pop ds
pop bx
pop ax
pop bp
ret
DispZhS endp
5、標準VGA進入圖形模式的方法
;進入640×480×16色模式
;setmode:
;對640*480*16和320*論200*256是標準VGA模式,在各種VGA上都分別為12h和13h
mov ax, 12h
int 10h 19_24.rar (39.92 KB)
關於中文支持的幾點想法:
1、“字符集”只是面向用戶的對問題的高層次的抽象。
當妳把中文文檔保存在軟盤上帶回家時,上面存放著的是“字符集”中編碼的集合,它們以壹種成為標準的方式定義著唯壹的壹個現實世界存在的漢字。但另壹方面,這些編碼本身並不說明任何其它關於這個漢字的信息,比如發音?偏旁?等等,當妳在另外壹臺機器上查看這個文檔時,必需有壹個“顯示層”處在人和計算機之間,而這個顯示層如何實現並不重要,唯壹重要的是它也必需知道編碼與漢字的對應關系,當它讀到壹個處於某個“字符集”的編碼時,它就通過自身維護著的壹個代碼轉換表將標準的編碼轉換成自己的字形信息碼,這是壹個查表的過程,之後它根據查找到的信息“繪制”出壹個特定的漢字。
2、這就意味著重要的是標準,而不是實現,當妳要在壹個英文平臺上顯示漢字時,唯壹困難的是確定壹個相互不沖突的標準字符集,至於要顯示出什麽形狀根本不是問題。
3、為了確保兼容和跨平臺,從軟件的角度說最好自帶字庫,通過這個實例清楚了如何做到自帶字庫,事實上因為這裏實現的程序是以字而不是象通常那樣以字節為單位讀字形信息,造成通常點陣字庫中的編碼無法直接拿來用,那樣字的兩邊恰好顛倒,必須對每兩個字節交換壹次才能被它正確顯示出來。但是不難通過修改DispZhC中的代碼實現通用。
4、要實現矢量字形原理是壹樣的,但是需要較多的數學方法,這就知道了理論的用途。想想為什麽壹些計算機大師最初的動力竟是因為酷愛遊戲。