1.繪制像素
[cpp] view plaincopyprint?
-----------------------------------------------------------------------
INT 0x10可識別的視頻圖形模式
--------------------------------------------------------------------
模式 分辨率(列*行,像素) 顏色數
6 640x200 2
0DH 320x200 16
0EH 640x350 16
0FH 640x350 2
10H 640x200 16
11H 640x480 2
12H 640x480 16
13H 320x200 256
6AH 800x600 16
-----------------------------------------------------------------------
當視頻控制器處於圖形模式時,INT 0x10的功能0CH在屏幕上繪制一個像素點。(功能0CH執行的相當慢)
[cpp]
-----------------------------------------------------------------------
INT 0x10 功能0CH
---------------------------------------------------------------
描述:
寫像素
接受參數:
AH 0CH
AL 像素值
BH 視頻頁
CX X坐標
DX Y坐標
返回值:
無
注意:
視頻顯示必須處於圖形模式下。像素值的范圍和坐標范圍與當前的圖形模式有關。
如果AL的位7置位,新的像素同當前像素的內容進行異或運算。
-------------------------------------------------------------------------
示例,畫線程序:
[cpp]
# This program draws a straight line in graphics mode.
# 2012-12-24 20:42
# [email protected]
.section .text
.global _start
.code16
_start:
jmp main
clear_screen: # 清屏函數
movb $0x06, %ah # 功能號0x06
movb $0, %al # 上卷全部行,即清屏
movb $0, %ch # 左上角行
movb $0, %ch # 左上角列
movb $24, %dh # 右下角行
movb $79, %dl # 右下角列
movb $0x07, %bh # 空白區域屬性
int $0x10
ret
main:
movw %cx, %ax
movw %ax, %ds
movw %ax, %es
call clear_screen # 清屏
# 設置成圖形模式,0x6a為800x600, 16種顏色
movb $0, %ah # 功能號0x0
movb $0x6a, %al # 顯示模式
int $0x10
# 畫一條直線
movb $0x0, %bh # 視頻頁
movw $300, %dx # y坐標
movw $100, %cx # x坐標
movb $0x0c, %ah # 功能號
movb $9, %al # 像素值(顏色)
1:
int $0x10
incw %cx # 下一個像素
cmpw $700, %cx # 是否到了結束位置
jne 1b
1:
jmp 1b
.org 0x1fe, 0x90
.word 0xaa55
結果:
2.圖形模式用功能0x13顯示字符串
[cpp]
# This program draws text and a straight line in graphics mode.
# 2012-12-24 20:42
# [email protected]
.section .text
.global _start
.code16
_start:
jmp main
clear_screen: # 清屏函數
movb $0x06, %ah # 功能號0x06
movb $0, %al # 上卷全部行,即清屏
movb $0, %ch # 左上角行
movb $0, %ch # 左上角列
movb $24, %dh # 右下角行
movb $79, %dl # 右下角列
movb $0x07, %bh # 空白區域屬性
int $0x10
ret
main:
movw %cx, %ax
movw %ax, %ds
movw %ax, %es
call clear_screen # 清屏
# 設置成圖形模式,0x6a為800x600, 16種顏色
movb $0, %ah # 功能號0x0
movb $0x6a, %al # 顯示模式
int $0x10
# 顯示文字
movw $msgstr,%ax
movw %ax, %bp
movw len, %cx
movb $0x13, %ah
movb $0, %al
movb $0x04, %bl
movb $0x0, %bh
movb $0x02, %dh
movb $0x04, %dl
int $0x10
# 畫一條直線
movb $0x0, %bh # 視頻頁
movw $300, %dx # y坐標
movw $100, %cx # x坐標
movb $0x0c, %ah # 功能號
movb $9, %al # 像素值(顏色)
1:
int $0x10
incw %cx # 下一個像素
cmpw $700, %cx # 是否到了結束位置
jne 1b
1:
jmp 1b
msgstr:
.asciz "line: start(100, 300), end(700, 300)\n"
len:
.int . - msgstr
.org 0x1fe, 0x90
.word 0xaa55
結果:
3.內存映射圖形
對於內存映射圖形視頻模式0x13最容易使用。這時屏幕像素映射為一個字節數組,每個像素一個字節。
共有320*200個像素,因為有256種顏色,所以每個像素一個字節。左上角像素對應地址0xa0000。
模式0x13中,每個整數色彩值表示調色板的色彩表的索引。調色板中每個項都由三個獨立的整數(0~63)構成,稱為RGB值。調色板的第0項控制著屏幕的背景色。
有兩個輸出端口用於控制視頻調色板:送往端口0x3c8的值表示要修改的調色板表項,送往端口0x3c9的是要修改的顏色值。
示例:
[cpp]
# This program draws color pixels at mode 0x13
# 2012-12-24 21:31
# [email protected]
.section .text
.global _start
.code16
_start:
jmp main
#--------------------------------------------------------------
# 清屏函數:
# 設置屏幕背景色,調色板的索引0指代的顏色為背景色
clear_screen: # 清屏函數
movb $0x06, %ah # 功能號0x06
movb $0, %al # 上卷全部行,即清屏
movb $0, %ch # 左上角行
movb $0, %ch # 左上角列
movb $24, %dh # 右下角行
movb $79, %dl # 右下角列
movb $0x07, %bh # 空白區域屬性
int $0x10
ret
#----------------------------------------------------------------
# 設置顯示模式函數
set_video_mode:
movb $0, %ah # 功能號0x0
movb $MODE_0X13, %al # 顯示模式
int $0x10
ret
#---------------------------------------------------------------
# 顯示一些文字函數:
# 使用INT 0x10中斷0x13功能,顯示計算機當前工作的顯示模式
draw_some_text:
movw $msg_str, %bp # ES:BP為字符串地址
movw msg_len, %cx # 顯示字符數
movb $0x13, %ah # 功能號
movb $0, %al # 顯示模式
movb $TEXT_COLOR,%bl # 屬性值
movb $0, %bh # 視頻頁
movb $TEXT_ROW, %dh # 顯示起始行
movb $TEXT_COL, %dl # 顯示起始列
int $0x10
ret
#----------------------------------------------------------------
# 設置背景顏色為深藍色
set_screen_bk_color:
movw $VIDEO_PALLETE_PORT, %dx
movb $PA_INDEX_BACKGROUND, %al
outb %al, %dx
movw $COLOR_SELECTION_PORT, %dx
movb $0, %al # 紅
outb %al, %dx
movb $0, %al # 綠
outb %al, %dx
movb $18, %al # 藍(亮度18/63)
outb %al, %dx
ret
#----------------------------------------------------------------
# 通過寫顯存繪制一些像素點:
# 首先設置調色板索引1處的顏色為白色
# 然後通過寫顯存的方式,向ES:DI寫入數據(PA_INDEX_WHITE)
draw_some_pixels:
# 把索引1處的顏色改為白色(63,63,63)
movw $VIDEO_PALLETE_PORT, %dx
movb $PA_INDEX_WHITE, %al
outb %al, %dx
movw $COLOR_SELECTION_PORT, %dx
movb $63, %al # 紅
outb %al, %dx
movb $63, %al # 綠
outb %al, %dx
movb $63, %al # 藍
outb %al, %dx
# 設置ES的值
movw $VIDEO_SEG_GRAPHIC, %ax
movw %ax, %es
# 設置要顯示的像素位置的顯存地址(目的地址)
movw $(PIXEL_ROW_ST*320 + PIXEL_COL_ST), %di
movb $PA_INDEX_WHITE, %al
movw $PIXEL_COUNT, %cx
draw_a_pixel:
stosb
addw $5, %di
loop draw_a_pixel
ret
main:
movw %cx, %ax
movw %ax, %ds
movw %ax, %es
call clear_screen # 清屏
call set_video_mode # 設置顯示模式
call set_screen_bk_color # 設置背景顏色
call draw_some_text # 繪制字符串
call draw_some_pixels # 繪制像素
1:
jmp 1b
# 常量定義:
VIDEO_SEG_TEXT = 0xb800
VIDEO_SEG_GRAPHIC = 0xa000
VIDEO_PALLETE_PORT = 0x3c8
COLOR_SELECTION_PORT= 0x3c9
MODE_0X13 = 0x13
PA_INDEX_BACKGROUND = 0x0
PA_INDEX_WHITE = 0x1
TEXT_ROW = 0x01
TEXT_COL = 0x00
TEXT_COLOR = 0x04
PIXEL_ROW_ST = 100
PIXEL_COL_ST = 160-5*10
PIXEL_COUNT = 20
msg_str:
msg_mode:
.asciz "video mode: 0x13"
.org msg_mode+40, 0
msg_scr_res:
.asciz "screen resolution:320x200"
.org msg_scr_res+40, 0
msg_color_num:
.asciz "color num:256"
.org msg_color_num+40*4, 0
msg_babyos:
.asciz "The new Baby OS will have a GUI,but now it can only draw some pixels, haha..And merry Christmas!"
msg_len:
.int . - msg_str - 1
.org 0x1fe, 0x90
.word 0xaa55
結果:
注釋:
文字是用的BIOS INT 0x10顯示的,VGA的0x13模式下顯示的文字為40列x25行,字符框8x8,看上去有點丑,以後再研究下超級VGA(SVGA)吧~