Microsoft KB Archive/37422

= Using Assembler to Save and Restore Text Mode Screens in QB =

Article ID: 37422

Article Last Modified on 8/16/2005

-

APPLIES TO


 * Microsoft QuickBasic 4.0
 * Microsoft QuickBASIC 4.0b
 * Microsoft QuickBasic 4.5 for MS-DOS
 * Microsoft BASIC Compiler 6.0
 * Microsoft BASIC Compiler 6.0b
 * Microsoft BASIC Professional Development System 7.0

-



This article was previously published under Q37422



SUMMARY
This article contains a sample program that demonstrates how to save and restore text screens using an assembly language routine called from compiled Basic.

This information applies to Microsoft QuickBasic versions 4.00, 4.00b, and 4.50 for MS-DOS; to the Microsoft Basic Compiler versions 6.00 and 6.00b for MS-DOS; and to Microsoft Basic PDS Version 7.00 for MS-DOS.



MORE INFORMATION
The method (below) calls an assembly-language routine to store the screen in an array, then restore it. This method is similar to the graphics mode GET and PUT statements. The October 27, 1987, issue of &quot;PC Magazine&quot; has an example of an assembly-language routine that does this; however, the code needs to be modified for QuickBasic version 4.00. The modified programs are as follows:

The following is DEMO.BAS, that demonstrates saving and restoring the text mode screen by calling two assembly language routines from QuickBasic: Defint A-Z '$Dynamic Dim Storage(1999) FirstLine = 1 LastLine = 5 Cls For X = 1 To 15 Color X      Print String$(80, X + 64); Next Locate 20 Print &quot;Press a key to save the screen&quot;; While Inkey$ = &quot;&quot; : Wend 'Call Ptr86(Segment, Address, Varptr(Storage(0))) ' For QB 3.00. Segment=VARSEG(Storage(0)) ' For QB 4.00 Address=VARPTR(Storage(0)) ' For QB 4.00 Call ScrnSave(FirstLine, LastLine, Segment, Address) Cls Print &quot;Press a key to restore the top&quot;; While Inkey$ = &quot;&quot; : Wend 'Call Ptr86(Segment, Address, Varptr(Storage(0))) ' For QB 3.00. Segment=VARSEG(Storage(0)) ' For QB 4.00 Address=VARPTR(Storage(0)) ' For QB 4.00 Call ScrnRest(FirstLine, LastLine, Segment, Address) The following is SCRNSAVE.ASM, an assembly language routine. SCRNSAVE.ASM saves a portion of the text screen in QuickBasic: Code       Segment Byte Public 'Code' Assume CS:Code Public ScrnSave

ScrnSave   Proc    Far

Begin:     Push  BP            ;save registers for Basic

;* Push DS  DELETE THIS LINE

Mov  BP,SP         ;locate stack to get variable ;addresses later

PUSH DS            ;* SAVE THE DATA SEGMENT PUSH ES            ;* SAVE THE EXTRA SEGMENT

Mov  DX,0          ;look at low memory using ES            Mov   ES,DX Mov  BX,0B000h     ;assume monochrome screen segment for ;now Mov  AL,ES:[410h]  ;get the equipment list And  AL,48         ;just look at the monitor type Cmp  AL,48         ;is it monochrome? JZ   Get_Params    ;if yes, skip over adding 800h Add  BX,800h       ;if no, adjust for color-screen memory

Mov  AL,ES:[487h]  ;if an EGA is present, AL will not be                                ;zero Cmp  AL,0          ;is it an EGA? JNZ  Get_Params    ;if yes, leave DX set to zero as a                                ;flag for later Mov  DX,3DAh       ;if no, specify the port to check for ;retrace

Get_Params: Push BX            ;save the screen segment for later

;* Mov  SI,[BP+08] ;get the starting address of the ;storage array ;* change to BP+6 Mov  SI,[BP+06]    ;get the starting address of the ;storage array Mov  DI,[SI]       ;and put it into DI

;* Mov  SI,[BP+10] ;get the segment for the array ;* change to BP+8 Mov  SI,[BP+8]    ;get the segment for the array

Mov  ES,[SI]       ;and assign it to ES

;* Mov  SI,[BP+12]    ;get the address for LastLine ;* change to BP+10 Mov  SI,[BP+10]    ;get the address for LastLine

Mov  AL,[SI]    ;and put it into AL            Mov   CL,160     ;prepare to multiply times 160 Mul  CL         ;now AX holds the last screen address to                             ;save Mov  BX,AX      ;save it in BX for later

;* Mov  SI,[BP+14]    ;get the address for FirstLine ;* change to BP+12 Mov  SI,[BP+12]  ;get the address for FirstLine Mov  AL,[SI]     ;put it into AL            Dec   AL          ;adjust 1-25 to 0-24 Mul  CL          ;calculate actual starting address on                              ;screen Mov  SI,AX       ;now SI points to the source address

Sub  BX,AX       ;calculate the number of bytes to copy Mov  CX,BX       ;put it into CX for Rep or Loop below Shr  CX,1        ;divide CX by 2 to obtain the number of                              ;words Pop  DS          ;retrieve the screen segment saved ;earlier Cld              ;all data moves below will be forward Cmp  DL,0        ;are we doing monochrome or EGA? JZ   Mono        ;if monochrome, skip over the retrace

No_Retrace: In   AL,DX       ;get the video-status byte Test AL,1        ;test just the horizontal retrace part JNZ  No_Retrace  ;if doing a retrace, wait until it is                              ;not Retrace:   In    AL,DX       ;get the status byte again Test AL,1        ;are we currently doing a retrace? JZ   Retrace     ;if no, wait until we are Lodsw            ;now get the word from the screen Stosw            ;and put it into the array Loop No_Retrace  ;loop until done Jmp  Exit        ;skip over the monochrome routine and ;exit Mono:      Rep   Movsw       ;move the data in one operation

Exit:      POP   ES          ;* ADD THIS LINE Pop  DS          ;restore registers for Basic Pop  BP            Ret   8           ;return skipping the passed parameters

ScrnSave   Endp Code       Ends End  ;* REMOVE THE LABEL Begin The following is SCRNREST.ASM, which restores a portion of the text screen in the QuickBasic program: Code       Segment Byte Public 'Code' Assume CS:Code Public ScrnRest

ScrnRest   Proc    Far

Begin:     Push  BP            ;save registers for Basic

;* Push DS  DELETE THIS LINE

Mov  BP,SP       ;locate stack to get variable addresses ;later PUSH DS          ;* ADD THIS LINE PUSH ES          ;* ADD THIS LINE

Mov  DX,0        ;look at low memory using ES            Mov   ES,DX Mov  BX,0B000h   ;assume monochrome screen segment for ;now Mov  AL,ES:[410h];get the equipment list And  AL,48       ;just look at the monitor type Cmp  AL,48       ;is it monochrome? JZ   Get_Params  ;if yes, skip over adding 800h Add  BX,800h     ;if no, adjust for color-screen memory

Mov  AL,ES:[487h];if an EGA is present, AL will not be                              ;zero Cmp  AL,0        ;is it an EGA? JNZ  Get_Params  ;yes, leave DX set to zero as flag for ;later Mov  DX,3DAh     ;no, specify the port to check for ;retrace Get_Params: Mov  ES,BX       ;set ES to the appropriate screen ;segment

;* Mov  DI,[BP+12]    ;get the address for LastLine ;* change to BP+10 Mov  DI,[BP+10]    ;get the address for LastLine

Mov  AL,[DI]      ;and put it into AL            Mov   CL,160       ;prepare to multiply times 160 Mul  CL           ;now AX holds last screen address to                               ;restore Mov  BX,AX        ;save it in BX for later

;* Mov  DI,[BP+14]    ;get the address for FirstLine ;* change to BP+12 Mov  DI,[BP+12]  ;get the address for FirstLine

Mov  AL,[DI]     ;put it into AL            Dec   AL          ;adjust 1-25 to 0-24 Mul  CL          ;calculate actual starting address on                              ;screen Mov  DI,AX       ;now DI points to the destination ;address Sub  BX,AX       ;calculate the number of bytes to copy Mov  CX,BX       ;put it into CX for Rep or Loop below Shr  CX,1        ;divide CX by 2 to obtain the number of                              ;words ;* Mov  SI,[BP+10]    ;get the segment of the storage array ;* change BP + 8 Mov  SI,[BP+8]    ;get the segment of the storage array

Mov  AX,[SI]       ;and save it in AX for a moment

;* Mov  SI,[BP+08] ;get the address of the first array ;element ;* change to BP+6 Mov  SI,[BP+06]  ;get the address of the first array ;element Mov  SI,[SI]     ;and put it into SI            Mov   DS,AX       ;okay to change DS after getting all ;variables Cld              ;all data moves below will be forward Cmp  DL,0        ;are we doing monochrome or EGA? JZ   Mono        ;if monochrome, skip over the retrace

No_Retrace: In   AL,DX       ;get the video status byte Test AL,1        ;test just the horizontal retrace part JNZ  No_Retrace  ;if doing a retrace, wait until it is                              ;not Retrace:   In    AL,DX       ;get the status byte again Test AL,1        ;are we currently doing a retrace? JZ   Retrace     ;if no, wait until we are Lodsw            ;now get the word from the screen Stosw            ;and put it into the array Loop No_Retrace  ;loop until done Jmp  Exit        ;skip over the monochrome routine and ;exit Mono:      Rep   Movsw       ;move the data in one operation

Exit:      POP   ES          ;* ADD THIS LINE Pop  DS          ;restore registers for Basic Pop  BP            Ret   8           ;return skipping the passed parameters

ScrnRest   Endp Code       Ends End  ;* REMOVE THE LABEL Begin

Additional query words: QuickBas BasicCom

Keywords: KB37422

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.