程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編源代碼之圖形顯示方式屏幕的保存和恢復

匯編源代碼之圖形顯示方式屏幕的保存和恢復

編輯:匯編語言

在程序中常常要暫時的保存圖形顯示方式屏幕上的內容,然後把自己的信息輸出到屏幕上,結束後再恢復原來的屏幕內容,特別在內存駐留程序彈出一個窗口時更要用到,但是圖形方式下顯示緩沖區的容量巨大,在常用的 80 x 25 文本方式下,顯示緩沖區僅大小僅為 80 x 25 x 2 = 4000 字節,而在模式 13H 320 x 200 x 256 色時為 320 x 200 = 64000 字節,現在常用的高彩色、真彩色下如 800 x 600 x 65535 色時為 800 x 600 x 2 = 960000 字節,涉及到如此大的數據量程序必須使用磁盤交換方法或用到 XMS 做為數據保存緩沖區,使編程復雜化。

本文用了 INT 10H 中不清除顯示內存設置新顯示模式的方法,使不管在什麼顯示方式下,用到的緩沖區大下都在 10K 左右,即使在 1024 x 768 x 16.7M 色也能正常保存。

本程序的適用范圍為保存屏幕後自己的程序僅僅使用文本模式 3 的情況,如果要用到圖形模式,那麼還是要保存全部的顯示緩沖區。在兼容性方面,由於使用 VESA 標准功能,在現在的 PCI/VESA 顯示卡上都能正常運行,我發現唯一不能運行的是有一段時期生產的 TVGA 8900/9000 卡,因為此卡在 VESA 功能剛出現的時候生產,支持 VESA 的偽彩色顯示模式,卻又不支持很多其他的 VESA 功能。大家找到克服的方法告訴我一聲。

本程序要用到的一些中斷的說明如下:

INT 10H 的 00H 功能,設置顯示模式:

功能 入口參數 出口參數

INT 10H 的 00H功能

設置顯示模式 AH = 00H  

AL = 模式(如果位 7 置位,則不清除顯示緩沖區)

INT 10H 的 1BH 功能,檢測是否 VGA 卡:

功能 入口參數 出口參數

INT 10H 的 1BH功能

取 VGA/MCGA 的功能、狀態信息 AH = 1BH AL = 1BH 成功(說明顯示卡為 VGA 以上)
  ES:DI 返回狀態信息

BX = 0000

AL <> 1BH 非VGA/MCGA 顯示卡

ES:DI 指向 64 字節緩沖區

INT 10H 的 1CH 功能,保存/恢復視頻狀態:

功能 入口參數 出口參數

INT 10H 的 1C00H 功能

返回狀態緩沖區容量 AX = 1C00H AL = 1CH 成功

BX = 需要的 64 字節塊數目

INT 10H 的 1C01H 功能

保存視頻狀態 AX = 1C01H  

ES:BX 指向緩沖區

INT 10H 的 1C02H 功能

恢復視頻狀態 AX = 1C01H  

CX = 要求的狀態

位 0 = 恢復視頻硬件狀態

位 1 = BIOS 數據區

位 2 = 彩色寄存器和 DAC 狀態

ES:BX 指向緩沖區(用1C01H功能保存下來的)

INT 10H 的 4FH 功能,VESA 功能:

功能 入口參數 出口參數

INT 10H 的 4F00H功能

取顯示卡 VESA 信息 AX = 4F00H AL = 4FH 說明顯示卡支持VESA

AH = 00H 成功

AH = 01H 失敗

ES:DI 指向緩沖區 (256 字節) AL <> 4FH 顯示卡不支持VESA

INT 10H 的 4F05H功能

控制對 VESA 顯示卡視頻 RAM 的訪問 BH = 00H 選視頻內存窗口

DX = 視頻內存窗口地址 AH = 00H 成功

AH = 01H 失敗

BH = 01H 取視頻內存窗口 AH = 00H 成功

DX = 視頻內存窗口地址

AH = 01H 失敗

INT 33H 的 16H/17H 功能,保存/恢復鼠標驅動程序狀態:

功能 入口參數 出口參數

INT 33H 的 0015H功能

確定保存鼠標驅動程序狀態所需

的空間 AX = 0015H BX = 所需大小

INT 33H 的 0016H功能

保存鼠標驅動程序狀態 AX = 0016H  

BX = 緩沖區大小(用 0015H 獲得)

ES:DX 指向緩沖區

INT 33H 的 0017H功能

恢復鼠標驅動程序狀態 AX = 0017H  

BX = 緩沖區大小(用 0015H 獲得)

ES:DX 指向緩沖區

源程序:

;by Luo Yun Bin

;http://asm.yeah.net

;這個子程序用來檢測顯示卡的類型,鼠標狀態等等

;在程序初始化時執行

;文中要用到的一些緩沖區請自己定義,注意大小!

flag db ? ;標志位,位 7 置 1 表示安裝了鼠標

vga_type db ? ;顯示卡類型

video_mode db ? ;顯示模式

vga_win1 dw ? ;視頻窗口,暫存 VESA 的窗口狀態

vga_win2 dw ? ;

vga_win3 dw ? ;

...

TEST_VGA PROC

push 0 ;檢測是否安裝鼠標驅動程序

pop ds

cmp word ptr ds:[33h*4],0

jz no_mouse

or cs:flag,10000000b ;has mouse installed

no_mouse:

push cs

pop ds

mov ah,1bh ;檢測是否是 VGA 以上顯示卡

xor bx,bx

mov di,offset file_end

int 10h

cmp al,1bh

jnz tv_no_vga

mov ax,4f00h ;檢測是否支持 VESA 功能

mov di,offset file_end

int 10h

cmp al,4fh

jz tv_is_vesa

mov dx,3c4h ;檢測是否 TVGA 9000 卡

mov al,0eh ;這一段是照抄的,找不到資料

out dx,al

inc dx

in al,dx

mov bl,al

xor al,al

out dx,al

in al,dx

xchg al,bl

out dx,al

test bl,2

jnz tv_is_tvga

mov dx,3cdh ;檢測是否 ET6000 卡

in al,dx

mov ah,al

mov al,11h

out dx,al

in al,dx

xchg ah,al

out dx,al

cmp ah,11h

jz tv_is_tseng

mov vga_type,4

ret

tv_is_vesa:

mov vga_type,1

ret

tv_is_tvga:

mov vga_type,2

ret

tv_is_tseng:

mov vga_type,3

ret

tv_no_vga:

int 20h ;非 VGA 卡退出

TEST_VGA ENDP

...

;================================================================

;保存顯示緩沖區內容並設置新的顯示模式到 80 x 25 文本 (模式 3)

SAVE_SCR PROC

push ds

push es

test flag,10000000b ;見前面

jz ss_no_mouse

mov ax,16h ;保存鼠標狀態

mov dx,offset mouse_buffer

int 33h

ss_no_mouse:

mov ax,1c01h ;保存視頻狀態

mov bx,offset video_buffer

mov cx,7

int 10h

mov ah,0fh ;保存原顯示模式

int 10h

mov video_mode,al

cmp al,3 ;80 x 25 x 16 色

jz ss_mode3

cmp al,7 ;80 x 25 黑白

jz ss_mode7

xor ax,ax ;以下為圖形方式保存顯示緩沖區

call vga_page

call vga_base

call save_vram

mov ax,0083h ;設置新的顯示模式,不清除顯示內存

int 10h

push 0b800h

pop ds ;保存顯示內存

xor si,si

mov cx,1000h

mov di,offset ram_buffer

push cs

push ds

cld

rep movsb

xor di,di ;

mov cx,80*25

mov ax,57b1h ;填充背景,不然有亂字符

cld

rep stosw

scr_ret
  pop es

pop ds

ret

ss_mode3:

call save_vram ;顯示模式 3 保存顯示 RAM

jmp short scr_ret

ss_mode7:

push 0b000h ;顯示模式 7 保存顯示 RAM

pop ds

call save_vram1

mov ax,3

int 10h

call restore_vram

jmp short scr_ret

SAVE_SCR ENDP

SAVE_VRAM PROC

push 0b800h ;把顯示內存保存到自己的緩沖區

pop ds

save_vram1:

push cs

pop ds

xor si,si

mov di,offset ram_buffer

mov cx,2000h

cld

rep movsb

ret

SAVE_VRAM ENDP

RESTORE_VRAM PROC

push 0b800h ;恢復顯示緩沖區內容

pop es

restore_vram1:

xor di,di

push cs

pop ds

mov si,offset ram_buffer

mov cx,2000h

cld

rep movsb

ret

RESTORE_VRAM ENDP

VGA_PAGE PROC

cmp vga_type,1

jnz other_vga1

cmp ah,1

jz vp_vesa2

cmp ah,2

jz vp_vesa1

mov ax,4f05h ;保存 VESA 顯示卡狀態

mov bx,0100h

int 10h

mov vga_win1,dx

mov ax,4f05h

mov bx,0101h

int 10h

mov vga_win2,dx

vp_vesa1:

mov ax,4f05h

xor bx,bx

xor dx,dx

int 10h

mov ax,4f05h

mov bx,0001h

xor dx,dx

int 10h

ret

vp_vesa2:

mov ax,4f05h

xor bx,bx

mov dx,vga_win1

int 10h

mov ax,4f05h

mov bx,0001h

mov dx,vga_win2
  int 10h

ret

other_vga1:

cmp vga_type,3

jnz other_vga2

mov dx,3cdh

cmp ah,1

jz vp_tseng2

cmp ah,2

jz vp_tseng1

in al,dx

mov vga_win3,al

vp_tseng1:

xor al,al

out dx,al

ret

vp_tseng2:

mov al,vga_win3

out dx,al

vp_ret:

ret

other_vga2:

cmp vga_type,2

jnz vp_ret

mov al,0eh

mov dx,03c4h

cmp ah,1

jz vp_tvga2

out dx,al

inc dx

in al,dx

cmp ah,2

jz vp_tvga1

mov vga_win3,al

xor al,al

out dx,al

ret

vp_tvga1:

mov al,2

out dx,al

ret

vp_tvga2:

mov ah,vga_win3

out dx,ax

ret

VGA_PAGE ENDP

VGA_BASE PROC

mov dx,3c4h ;這一段是照抄的,找不到資料

mov ax,402h

out dx,ax

mov ax,704h

out dx,ax

mov dx,3ceh

mov ax,0ff08h

out dx,ax

mov ax,0c06h

out dx,ax

mov ax,204h

out dx,ax

mov ax,5

out dx,ax

ret

VGA_BASE ENDP

;====================================================

;本子程序為恢復原來的顯示內容

;在自己的程序執行完後使用

RESTORE_SCR PROC

push cs

pop ds

mov al,video_mode ;根據不同的原顯示模式不同處理

cmp al,3

jz rs_mode3

cmp al,7

jz rs_mode7

push 0b800h ;以下為圖形方式恢復顯示內容


  pop es

push cs

pop ds

mov si,offset ram_buffer

xor di,di

mov cx,1000h

cld

rep movsb ;恢復顯示 RAM

mov ah,2

call vga_page

call vga_base

call restore_vram

xor ah,ah ;恢復到原來的顯示模式

mov al,video_mode

or al,80h

int 10h

mov ah,1

call vga_base

jmp short rs_mode31

rs_mode3:

call restore_vram

rs_mode31:

push cs

pop es

push cs

pop ds

mov ax,1c02h ;恢復視頻狀態

mov bx,offset video_buffer

mov cx,7

int 10h

test flag,10000000b

jz rs_no_mouse

mov ax,17h ;恢復鼠標狀態

mov dx,offset mouse_buffer

int 33h

rs_no_mouse:

ret

rs_mode7:

mov ax,7 ;顯示模式 7 恢復

int 10h

push 0b000h

pop es

call restore_vram1

jmp short rs_mode31

RESTORE_SCR ENDP

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved