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 "PC Magazine" 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 "Press a key to save the screen"; While Inkey$ = "" : 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 "Press a key to restore the top"; While Inkey$ = "" : 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