KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q31573: QuickBASIC/MASM Programs in "PC Magazine" Incorrect

Article: Q31573
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | B_BasicCom | mspl13_basic
Last Modified: 28-DEC-1989

The sample QuickBASIC and MASM programs discussed in "PC Magazine"
October 13, 1987, on Pages 389-399 will not correctly work with
QuickBASIC Version 4.00.

The modified programs are as follows:

   === QP.BAS ===

   'QPrint.Bas - quick print demonstration for QuickBASIC

   Test$ = STRING$(20 * 80, "X")              'make a long string
   Colr% = 7
   LOCATE 1, 1
   CALL QPrint(Test$, Colr%)

   === QP.ASM ===

   ;QPRINT.ASM - performs Quick Printing in the QuickBASIC
   ;Note: Assemble this with MASM (2.00 or later)
   ;Copyright 1987, Ziff Communications Co.

   Code        Segment Byte Public 'Code'
               Assume  CS:Code
               Public  QPrint

   QPrint      Proc    Far

   Begin:      Push  BP         ;save registers for BASIC
               MOV   BP,SP      ;* ADD THIS LINE
               PUSH  DS         ;* ADD THIS LINE
               PUSH  ES         ;* ADD THIS LINE

               Mov   AH,3       ;specify BIOS service to read cursor position
               Mov   BH,0       ;on text page zero
               Int   10h        ;this service returns row/column in DH/DL

               Mov   AL,DH      ;put the current row number into AL
               Mov   CL,160     ;multiply by 160 to get start address of row
               Mul   CL         ;do the multiplication, answer ends up in AX
               Mov   DH,0       ;clear DH for the Add below, we only want DL
               Add   AX,DX      ;add the column once for the character byte
               Add   AX,DX      ;and once more for the attribute byte
               Mov   DI,AX      ;now DI holds starting address on the screen

               Xor   DX,DX      ;zero out DX to look at low memory using ES
               Mov   ES,DX
               Mov   BX,0B000h     ;assume the mono screen segment for now
               Mov   AL,ES:[463h]  ;look at the video controller port address
               Cmp   AL,0B4h     ;is it mono?
               JZ    Get_Params ;yes, skip over adding 800h to video segment
               Add   BX,800h    ;no, adjust BX for a color monitor
               Push  BX         ;and save it because the EGA test destroys BX

               Mov   AH,12h     ;specify EGA BIOS EGA special function servic
               Mov   BL,10h     ;request EGA information
               Int   10h        ;call the BIOS
               Cmp   BL,10h     ;if BL is still 10h, there's no EGA
               JNZ   EGA        ;it is an EGA, skip ahead
               Mov   DX,3DAh    ;not EGA, specify port to check for retrace

   EGA:        Pop   BX         ;get the video segment again

   Get_Params: ;* Mov   BP,SP   ;get stack pointer so you can find variables
               Mov   ES,BX      ;move whatever segment is correct into ES

               Mov   SI,[BP+06] ;get the color that was passed
               Mov   AH,[SI]    ;and put it into AH for screen writing below
               Mov   SI,[BP+08] ;put descriptor to X$ into SI
               Mov   CX,[SI]    ;put Len(X$) into CX for loop counter
               JCXZ  Exit       ;if CX is zero it's a null string, exit now
               Mov   SI,[SI+02] ;put address of first character in X$ into SI
               Cld              ;clear the direction flag to move data forwar

   Check_Mon:  Cmp   DL,0       ;are we on a mono or EGA system?
               JZ    Mono       ;yes, skip over the retrace stuff

   No_Retrace: In    AL,DX      ;get the video status byte from port number D
               Test  AL,1       ;test just the horizontal retrace bit
               JNZ   No_Retrace ;if doing a retrace, wait until it's not

   Retrace:    In    AL,DX      ;get the status byte again
               Test  AL,1       ;are we doing a retrace now?
               JZ    Retrace    ;no, wait until we are

   Mono:       Lodsb            ;get the character from X$ and increment SI
               Stosw            ;store both the character and attribute
               Loop  Check_Mon  ;loop until CX is zero

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

   QPrint      Endp
   Code        Ends
               End   ;* remove this label Begin

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.