在程序中常常要暫時的保存圖形顯示方式屏幕上的內(nèi)容,然后把自己的信息輸出到屏幕上,結(jié)束后再恢復(fù)原來的屏幕內(nèi)容,特別在內(nèi)存駐留程序彈出一個窗口時更要用到,但是圖形方式下顯示緩沖區(qū)的容量巨大,在常用的 80 x 25 文本方式下,顯示緩沖區(qū)僅大小僅為 80 x 25 x 2 = 4000 字節(jié),而在模式 13H 320 x 200 x 256 色時為 320 x 200 = 64000 字節(jié),現(xiàn)在常用的高彩色、真彩色下如 800 x 600 x 65535 色時為 800 x 600 x 2 = 960000 字節(jié),涉及到如此大的數(shù)據(jù)量程序必須使用磁盤交換方法或用到 XMS 做為數(shù)據(jù)保存緩沖區(qū),使編程復(fù)雜化。 本文用了 INT 10H 中不清除顯示內(nèi)存設(shè)置新顯示模式的方法,使不管在什么顯示方式下,用到的緩沖區(qū)大下都在 10K 左右,即使在 1024 x 768 x 16.7M 色也能正常保存。 本程序的適用范圍為保存屏幕后自己的程序僅僅使用文本模式 3 的情況,如果要用到圖形模式,那么還是要保存全部的顯示緩沖區(qū)。在兼容性方面,由于使用 VESA 標(biāo)準(zhǔn)功能,在現(xiàn)在的 PCI/VESA 顯示卡上都能正常運行,我發(fā)現(xiàn)唯一不能運行的是有一段時期生產(chǎn)的 TVGA 8900/9000 卡,因為此卡在 VESA 功能剛出現(xiàn)的時候生產(chǎn),支持 VESA 的偽彩色顯示模式,卻又不支持很多其他的 VESA 功能。大家找到克服的方法告訴我一聲。 本程序要用到的一些中斷的說明如下: INT 10H 的 00H 功能,設(shè)置顯示模式: 功能 入口參數(shù) 出口參數(shù) INT 10H 的 00H功能 設(shè)置顯示模式 AH = 00H AL = 模式(如果位 7 置位,則不清除顯示緩沖區(qū)) INT 10H 的 1BH 功能,檢測是否 VGA 卡: 功能 入口參數(shù) 出口參數(shù) INT 10H 的 1BH功能 取 VGA/MCGA 的功能、狀態(tài)信息 AH = 1BH AL = 1BH 成功(說明顯示卡為 VGA 以上) ES:DI 返回狀態(tài)信息 BX = 0000 AL <> 1BH 非VGA/MCGA 顯示卡 ES:DI 指向 64 字節(jié)緩沖區(qū) INT 10H 的 1CH 功能,保存/恢復(fù)視頻狀態(tài): 功能 入口參數(shù) 出口參數(shù) INT 10H 的 1C00H 功能 返回狀態(tài)緩沖區(qū)容量 AX = 1C00H AL = 1CH 成功 BX = 需要的 64 字節(jié)塊數(shù)目 INT 10H 的 1C01H 功能 保存視頻狀態(tài) AX = 1C01H ES:BX 指向緩沖區(qū) INT 10H 的 1C02H 功能 恢復(fù)視頻狀態(tài) AX = 1C01H CX = 要求的狀態(tài) 位 0 = 恢復(fù)視頻硬件狀態(tài) 位 1 = BIOS 數(shù)據(jù)區(qū) 位 2 = 彩色寄存器和 DAC 狀態(tài) ES:BX 指向緩沖區(qū)(用1C01H功能保存下來的) INT 10H 的 4FH 功能,VESA 功能: 功能 入口參數(shù) 出口參數(shù) INT 10H 的 4F00H功能 取顯示卡 VESA 信息 AX = 4F00H AL = 4FH 說明顯示卡支持VESA AH = 00H 成功 AH = 01H 失敗 ES:DI 指向緩沖區(qū) (256 字節(jié)) AL <> 4FH 顯示卡不支持VESA INT 10H 的 4F05H功能 控制對 VESA 顯示卡視頻 RAM 的訪問 BH = 00H 選視頻內(nèi)存窗口 DX = 視頻內(nèi)存窗口地址 AH = 00H 成功 AH = 01H 失敗 BH = 01H 取視頻內(nèi)存窗口 AH = 00H 成功 DX = 視頻內(nèi)存窗口地址 AH = 01H 失敗 INT 33H 的 16H/17H 功能,保存/恢復(fù)鼠標(biāo)驅(qū)動程序狀態(tài): 功能 入口參數(shù) 出口參數(shù) INT 33H 的 0015H功能 確定保存鼠標(biāo)驅(qū)動程序狀態(tài)所需 的空間 AX = 0015H BX = 所需大小 INT 33H 的 0016H功能 保存鼠標(biāo)驅(qū)動程序狀態(tài) AX = 0016H BX = 緩沖區(qū)大小(用 0015H 獲得) ES:DX 指向緩沖區(qū) INT 33H 的 0017H功能 恢復(fù)鼠標(biāo)驅(qū)動程序狀態(tài) AX = 0017H BX = 緩沖區(qū)大小(用 0015H 獲得) ES:DX 指向緩沖區(qū) 源程序: ;by Luo Yun Bin ;http://asm.yeah.net ;這個子程序用來檢測顯示卡的類型,鼠標(biāo)狀態(tài)等等 ;在程序初始化時執(zhí)行 ;文中要用到的一些緩沖區(qū)請自己定義,注意大?。? flag db ? ;標(biāo)志位,位 7 置 1 表示安裝了鼠標(biāo) vga_type db ? ;顯示卡類型 video_mode db ? ;顯示模式 vga_win1 dw ? ;視頻窗口,暫存 VESA 的窗口狀態(tài) vga_win2 dw ? ; vga_win3 dw ? ; ... TEST_VGA PROC push 0 ;檢測是否安裝鼠標(biāo)驅(qū)動程序 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 ... ;================================================================ ;保存顯示緩沖區(qū)內(nèi)容并設(shè)置新的顯示模式到 80 x 25 文本 (模式 3) SAVE_SCR PROC push ds push es test flag,10000000b ;見前面 jz ss_no_mouse mov ax,16h ;保存鼠標(biāo)狀態(tài) mov dx,offset mouse_buffer int 33h ss_no_mouse: mov ax,1c01h ;保存視頻狀態(tài) 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 ;以下為圖形方式保存顯示緩沖區(qū) call vga_page call vga_base call save_vram mov ax,0083h ;設(shè)置新的顯示模式,不清除顯示內(nèi)存 int 10h push 0b800h pop ds ;保存顯示內(nèi)存 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 ;把顯示內(nèi)存保存到自己的緩沖區(qū) 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 ;恢復(fù)顯示緩沖區(qū)內(nèi)容 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 顯示卡狀態(tài) 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, |