• 注册
  • 关于作者
    企业认证:趣记站长
    关注 6 粉丝 4 喜欢 9 内容 992
    江西省·南昌市
    聊天 送礼
    • 查看作者
    • 图形显示方式屏幕的保存和恢复

      在程序中常常要暂时的保存图形显示方式屏幕上的内容,然后把自己的信息输出到屏幕上,结束后再恢复原来的屏幕内容,特别在内存驻留程序弹出一个窗口时更要用到,但是图形方式下显示缓冲区的容量巨大,在常用的 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 标准功能,

      检测DOS程序执行的目录
      用MASM32编程获取并显示WinRAR的路径 ,MASM-两个16位二进制数减法模拟,一个旋转的3D箱子(动画),用汇编破解cmos密码,真正意义上的前台窗口切换,检测DOS程序执行的目录,如何产生一个BMP文件,图形显示方式屏幕的保存和恢复,高级语言反汇编程序的函数调用过程,汇编语言的未来展望,定时器时间数据转换子程序分析,汇编语言命令参数程序的编写,win32asm原理,掀起硬盘主引导扇区的神秘面纱
      汇编语言

      在现在的 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

      如何产生一个BMP文件
      用MASM32编程获取并显示WinRAR的路径 ,MASM-两个16位二进制数减法模拟,一个旋转的3D箱子(动画),用汇编破解cmos密码,真正意义上的前台窗口切换,检测DOS程序执行的目录,如何产生一个BMP文件,图形显示方式屏幕的保存和恢复,高级语言反汇编程序的函数调用过程,汇编语言的未来展望,定时器时间数据转换子程序分析,汇编语言命令参数程序的编写,win32asm原理,掀起硬盘主引导扇区的神秘面纱
      汇编语言

    • 0
    • 0
    • 0
    • 97
    • 单栏布局 侧栏位置: