home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / basic / library / qb_pds / dos / dosbasic / fhelp.doc < prev    next >
Encoding:
Text File  |  1990-12-19  |  29.2 KB  |  620 lines

  1. ;
  2. ;DOS, Equipment and File Utilities
  3.  
  4. =======================================================================
  5.     Copyright (C) Copr. 1990 by Sidney J. Kelly
  6.             All Rights Reserved.
  7.             Sidney J. Kelly
  8.             150 Woodhaven Drive
  9.             Pittsburgh, PA 15228
  10.             home phone 412-561-0950 (7pm to 9:30pm EST)
  11.  
  12.      CompuServe   70043,1656
  13.      Genie        S.KELLY8
  14.  
  15. =======================================================================
  16.  
  17.         These routines provide information concerning the hardware/software
  18. environment.  A few routines are duplicated in PDS 7.1/QBX, though not with
  19. the same parameters.  Some routines provide information about the DOS
  20. status of a drive or file names.  Some routines even return information
  21. without needing ON ERROR GOSUB.  A fair number of hardware routines are
  22. provided.
  23.         Because I do not have access to PDS 7.x/QBX and its far string
  24. library, I believe that any of the routines that obtain input or make output
  25. to strings will not work correctly.  Some MASM code is shown below to
  26. demonstrate how to fix the routines so that they will do the same thing inside
  27. PDS 7.x/QBS.  Jim Mack has released some routines for PDS on COMPUSERVE MSSYS
  28. TRIMS.ASM.  It shows how to pass far strings inside PDS.
  29.  
  30.  =================================================================
  31.   DECLARE FUNCTION ACTUALEXTND% ()
  32.   Returns:
  33.         Actual amount of extended memory installed on 80286, 80386 or 80486
  34.         machine as stored in CMOS RAM
  35.         If clock battery is bad, will return a -1
  36.  
  37.  =================================================================
  38.   DECLARE FUNCTION ANSICHECK%()
  39.        IF ANSICHECK% THEN
  40.           PRINT "ANSI.SYS is installed."
  41.  
  42.   Source:  Disassembled COMMAND.COM Version 3.3 of CLS command
  43.                 xxxx:2B62h is the beginning of the routine
  44.  
  45.                 VERY FAST and NOT MESSY!!!!
  46.  
  47.  This is the same method that COMMAND.COM uses to test for ANSI.SYS
  48.  so every utility had better allow for this testing method.
  49.  
  50.   NOTE: PC Magazine's ANSI.COM even if turned off will still report ANSI.SYS
  51.         present, (it was planned that way so it would handle CLS).
  52.  
  53.  =================================================================
  54.   DECLARE SUB BEEPER
  55.   BEEPER
  56.   Primarily used to show you how to make sound in a somewhat machine
  57.   independent basis
  58.  
  59.  =================================================================
  60.  DECLARE FUNCTION CHECK87%()
  61.  Returns:
  62.          0 if no 80x87, or system equipment word not set.
  63.         87 if an 8087
  64.        -87 if 8087 emulation in use on an 80286 or 80386.  Because the
  65.              80287 has almost exactly the same instruction set as the
  66.             8087, few have felt a need to emulate the 80287.  I have not
  67.             seen an 80387 emulator in software.  The 80827 just includes
  68.             one new instruction (protected mode), nothing for use in
  69.             real mode.  80387 has transcendental math routines.*
  70.  
  71.        287 if an 80827
  72.        387 if an 80387 or 80487
  73.   More accurate than checking the equipment word.   QBX, Version 7
  74.   merely checks the equipment word to determine if an 80x87 is installed.
  75.   I guess that can be used as a software toggle.
  76.  
  77.   * Intel recently released an 80287 that has 80387 transcendental math
  78.     routines in it.  If someone sends me a new chip, I will write code
  79.     to test for it.
  80.  
  81.   Because of complaints about the traditional test with inexpensive clones
  82.   (See Jon Waterhouse letter in Byte, Nov. 1990, page 40)
  83.   routine first tests the equipment word in RAM bios.
  84.  
  85.  =================================================================
  86.  DECLARE FUNCTION DOSVER% ()
  87.  CALL DOSVER%
  88.  Returns DOS VERSION value as an integer, to get display value \ 100
  89.  E.g. DOS Version 3.3 is returned as 330
  90.  
  91.  =================================================================
  92.   DECLARE SUB DRVSPACE (DRIVE$,SPACE&)
  93.   checks if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
  94.   Drive of "@" gives the current drive
  95.   Invalid DRIVE$ gives a free space of 0
  96.   Note: DOS does not correctly adjust this if use JOIN or SUBST and
  97.   try to determine the size of a non-default drive.
  98.  
  99.  =================================================================
  100.   DECLARE SUB DRIVEALIAS ( ASSIGN%, DAPPEND%, NETWORK%, SHARE%)
  101.   CALL DRIVEALIAS( ASSIGN%, DAPPEND%, NETWORK%, SHARE%)
  102.   Purpose: To warn programmer that the logical drives may not be as they
  103.         seem, so if programmer desires to do some technical manipulation
  104.         he will be aware that it may not work.
  105.  
  106.  =================================================================
  107.   DECLARE SUB EQUIPMENT(ConvMem%,PrinterPorts%,ComPorts%)
  108.   Returns amount of Conventional Memory in KB
  109.           number of Parallel Ports
  110.           number of COM ports
  111.  
  112.  =================================================================
  113.   DECLARE SUB EXIST (FILNAME$, ErrCode%, Mode%)
  114.   CALL EXIST(FILENAME$+CHR$(0), ErrCode%, Mode%)
  115.   Filename$ must be an ASCII Null string (end in CHR$(0)).
  116.   Filename$ can not be a TYPEd string or a variable in a string array
  117.   because there is a chance that string will be outside DGROUP.  String
  118.   cocentenation is used to make sure it is in DGROUP.
  119.  
  120.   Mode%:
  121.        =  0 if just want to see if file exits
  122.        <> 0 if want to see if can read and write to file
  123.  
  124.   Returns ErrCode%    = 0 (False) if no error
  125.                       = True if an error,
  126.   Codes:
  127.        -1 = string wrong length
  128.         2 = file not found
  129.         3 = path not found
  130.         4 = no free handles
  131.         5 = access denied          (tried to read a subdirectory)
  132.        12 = invalid access code    (wont see this unless Mode% <> 0)
  133.        20 = Write protect error    (wont see this)
  134.        21 = Invalid drive
  135.        22 = Drive not ready        (floppy drive door open)
  136.        23 = unknown command
  137.        24 = CRC error
  138.        25 = Bad request structure
  139.        26 = Seek error
  140.        27 = Unknown disk format
  141.        28 = Sector not found
  142.        29 = Printer out of paper   (shouldn't see this)
  143.        30 = Write fault            (shouldn't see this)
  144.        31 = Read fault
  145.        32 = General, non-specific error (usually a network drive error)
  146.        35 = Invalid Disk Change    (shouldn't see this)
  147.  
  148.  =================================================================
  149.   DECLARE FUNCTION FINDDRIVES% ()
  150.   Returns number of current logical drives w/o any errors
  151.  
  152.   Because LASTDRIVE default value = 5, it is likely that
  153.   number of logical drives will be less than LASTDRIVE in CONFIG.SYS
  154.   This routine will miss a drive if there are gaps between logical drives
  155.   as can occur if SUBST is used.
  156.  
  157.  =================================================================
  158.   DECLARE SUB FLOPPYREADY (DRIVE$, ErrCode%)
  159.   Tests if floppy drive is ready, on a one floppy system
  160.   treats drive B: as equivalent to drive A:
  161.   ErrCode
  162.          128 = Time Out Error
  163.           80 = Track error
  164.          -1  = Drive$ is not valid
  165.           0  = All a.o.k.
  166.   Note : A critical error routine is not necessary for this routine to work
  167.  
  168.  =================================================================
  169.   DECLARE SUB FLOPPYDRIVES(NumDrives%)
  170.   Returns number of physical floppy drives in system
  171.  
  172.  =================================================================
  173.   DECLARE FUNCTION GETCPU% ()
  174.   Checks for CPU type
  175.   Returns:
  176.         88 for 8088
  177.         86 for 8086
  178.         20 for NEC V20
  179.         30 for NEC V30
  180.         186 for 80186 or 80188 (I have never seen an 80188 so no special test)
  181.         286 for 80286
  182.         386 for 80386DX or 80386SX
  183.         386 for 80486.  I offer no special test for 80486.
  184.  
  185.  =================================================================
  186.   DECLARE SUB GETCURRENTNAME (FName as STRING * 64, FileLength%)
  187.   Returns current filename for dos version 3.xx and above
  188.   if LEN(FName$) <> 64 then returns a FileLength% of -1
  189.  
  190.   FName$ can not be a TYPEd string or a variable in a string array
  191.   because there is a chance that string will be outside DGROUP.
  192.   This routine assumes that FName$ is a near string.
  193.   Function returns an error if DOS version < 3.xx since function is not
  194.   supported for that version.
  195.  
  196.  =================================================================
  197.  DECLARE SUB GETDOSVER (VERSION$)
  198.             VERSION$=SPACE$(4)
  199.             CALL GETDOSVER(VERSION$)
  200.  Returns DOS Version as a string
  201.  
  202.  =================================================================
  203.   DECLARE SUB GETDRIVE(DRIVE$)
  204.   CALL GETDRIVE(DRIVE$)
  205.   Returns current drive name
  206.   If LEN(DRIVE$)=0 then nothing happens
  207.  
  208.   Assumes that DRIVE$ is a near string, not TYPEd or part of a far string
  209.   array.  In other words, assumes DRIVE$ is in DGROUP
  210.  
  211.  =================================================================
  212.   DECLARE SUB GETFULLPATH (PATH$, PATHLEN%)
  213.   Returns current subdirectory path, with Drive:\, e.g. "A:\"
  214.   if LEN(Path$) <>  67 then returns a pathlen% of -1
  215.  
  216.   PATH$ can not be a TYPEd string or a variable in a string array
  217.   because there is a chance that string will be outside DGROUP.
  218.   This routine assumes that Path$ is a near string.
  219.  
  220.  =================================================================
  221.   DECLARE SUB GETSUB (PATH AS STRING * 64, PATHLEN%)
  222.   Returns current subdirectory path, without Drive:\, (i.e. no "A:\")
  223.   if LEN(Path$) not = to 64 then returns a pathlen% of -1
  224.  
  225.   PATH$ can not be a TYPEd string or a variable in a string array
  226.   because there is a chance that string will be outside DGROUP.
  227.   This routine assumes that Path$ is a near string.
  228.  
  229.  =================================================================
  230.   DECLARE SUB HARDDRIVES(NoDrives%)
  231.   Returns number of physical hard disks in system
  232.  
  233.  =================================================================
  234.   DECLARE SUB KILLPRINT (LptNum%)
  235.         CALL KILLPRINT(LptNum%)
  236.  
  237.   Halts LptNum%, by resetting and purging buffer. Printer reset to defaults
  238.   all non-default formats lost.  Will do nothing if errors noted, printer
  239.   is not busy.
  240.  
  241.  =================================================================
  242.   DECLARE FUNCTION MEM2INT% (SegAddress%,OffAddress%)
  243.   Reads word from memory and returns an integer value
  244.   Faster than PEEK(High_byte) * 256 + PEEK(Low_byte)
  245.  
  246.  =================================================================
  247.   DECLARE SUB MEM2STRING (TEXT$,SegAddress%,OffAddress%)
  248.   Reads bytes from memory and stores them into a string
  249.   number of bytes transferred is = LEN(Text$)
  250.   Assumes string is in near data (DGROUP) & not a fixed length string
  251.   or a user defined TYPE.
  252.  
  253.  =================================================================
  254.   DECLARE SUB OTHERMEMORY(EXTENDED%,EXPANDED%,XMS%)
  255.   Returns size of extended, expanded, and XMS memory.
  256.   Extended = only size that BIOS reports is free
  257.   Expanded = total installed.
  258.   XMS      = total installed.
  259.   Uses the rom ID byte approach to determine if extended memory supported.
  260.  
  261.  =================================================================
  262.   DECLARE SUB OTHEROPER (DPMI%, WINDOWS%, DESQ%)
  263.   CALL OTHEROPER(DPMI%, WINDOWS%, DESQ%)
  264.   Purpose: Checks if DPMI, or MS Windows or Quarterdeck DESQVIEW is active
  265.   Returns:
  266.         For each variable that exists -1
  267.         Else if multitasking environment does not exist then returns 0
  268.         Returns 0 if used with DOS versions < 3.x
  269.  
  270.  =================================================================
  271.  DECLARE FUNCTION PRINTRDY%(Lpt%)
  272.   Input:
  273.         Lpt% gives portnumber to test
  274.         Lpt%=1 for LPT1:, 2 for LPT2:, etc
  275.  
  276.   Returns:
  277.          0 if not ready
  278.         -1 (True) if ready
  279.  
  280.  =================================================================
  281.   DECLARE SUB PRINTSCREEN%(Mode%, Error%)
  282.   IF Error% THEN
  283.         printer error
  284.   else
  285.         all o.k.
  286.   end if
  287.  
  288.   Input:  0 = turn off printscreen key
  289.           1 = printscreen, then shut down key again
  290.   Prints to LPT1
  291.  
  292.  =======================================================================
  293.   DECLARE SUB REVERSESTRING (A$)
  294.   will reverse A$
  295.  
  296.   DECLARE SUB LEFTROTATE (A$)
  297.   will rotate a string one character to the left
  298.  
  299.   DECLARE SUB RIGHTROTATE (A$)
  300.   will rotate a string one character to the right
  301.  
  302.  =================================================================
  303.   DECLARE SUB SETDRIVE (DRIVE$,ErrCode%)
  304.   no change occurs if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
  305.   Returns   ErrCode% =  0 (False) if no errors
  306.                      = -1 (True)  if errors
  307.   error checking includes range check and real test if a change occurred
  308.  
  309.  =================================================================
  310.   DECLARE SUB SUBEXIST (PATH$+CHR$(0),ErrCode%)
  311.   Returns ErrCode%  =  0  (False) if no errors,
  312.                     = -1  (True)  if errors
  313.   If a drive change is required, subdirectory on other drive will be made
  314.   the "current" subdirectory on that other drive.
  315.  
  316.   PATH$ cannot be a TYPEd string or a variable in a string array
  317.   because there is a chance that string will be outside DGROUP.  String
  318.   cocentenation is used to make sure it is in DGROUP.
  319.  
  320.  =================================================================
  321.   DECLARE SUB SUBSTDRIVE (Drive$,ErrCode%)
  322.   CALL SUBSTDRIVE(Drive$,ErrCode%)
  323.  
  324.   Input:
  325.         Drive$ = letter between A to Z
  326.         If Drive$ ="" or is outside range, assume it is a request for
  327.         default drive information.
  328.  
  329.   Purpose: To warn programmer that the logical drives may not be as they
  330.         seem, so if programmer desires to do some technical manipulation
  331.         he will be aware that it may not work.
  332.  
  333.   Returns:
  334.         0 = o.k.
  335.         1 = invalid drive
  336.         2 = SUBST active on drive
  337.  
  338.  =================================================================
  339.   DECLARE SUB TRUENAME (OrigFile$+CHR$(0), TrueFName$, FileLength%)
  340.   Purpose:
  341.       Allows user to test for SUBST, ASSIGN, and JOIN using an
  342.       undocumented call for DOS Version 3.xx and above
  343.       The returned name will contain technically correct Drive: and Path
  344.       information.  However, the OrigFile$ is not checked so ? and * may be
  345.       used, the OrigFile$ may even be nonexistent.
  346.  
  347.   Shortcuts:
  348.   OrigFile$ = "." to obtain current drive & subdirectory name
  349.   OrigFile$ = ".." to obtain immediate parent drive & subdirectory name
  350.  
  351.   Usage:
  352.       TrueFName$ = STR$(67,0)
  353.       CALL TRUENAME(OrigFile$ + CHR$(0), TrueFName$, FileLength%)
  354.       IF FileLength% = -1 THEN
  355.            Error
  356.       ELSE
  357.            TrueFName$=LEFT$(TrueFName$, FileLength%)
  358.       END IF
  359.  
  360.  =================================================================
  361.  
  362.           QBASIC-MASM Interface Theory:
  363.           Generally QBASIC only keeps simple variables, (INT,
  364. LONGINT, SINGLE and DOUBLE, and STRINGS) in DGROUP.  Arrays and
  365. TYPE records are usually kept outside DGROUP, with only the
  366. STRING Descriptor or the undocumented Array descriptor kept in
  367. DGROUP.  Thus, the library routines assume that all information
  368. passed from simple variables is information about a near (DGROUP)
  369. address.  If we pass simple integers to MASM routines, and don't
  370. care to have MASM change those variables, we use BYVAL to send
  371. the information to MASM.  BYVAL speeds up variable access by a
  372. factor of two.  If we want to have MASM send information back
  373. about multiple variables, we must pass the address information
  374. for the variables without using BYVAL.  If we use arrays, we must
  375. use a combination of BYVAL & VARSEG and BYVAL & VARPTR to get the
  376. information we need to manipulate the information inside the
  377. arrays.  VARSEG and VARPTR are necessary because there is a very
  378. great chance that the arrays will be stored as far data (i.e. not
  379. stored in DGROUP).  If you must get an array in DGROUP, put the
  380. array in COMMON.
  381.           Text strings are sent by QBASIC as near address
  382. (relative to DS and DGROUP).  The fist value in the descriptor is
  383. the length of the string.  The second value is the offset address
  384. inside DGROUP.  Fixed length strings and TYPE record strings are
  385. not referenced with string descriptors.  For that reason, I don't
  386. allow such strings as variables in my routines.
  387.           PDS/QBX Version 7.x stores strings in FAR DATA, outside
  388. DGROUP.  Special routines are offered in the programmer's package
  389. to find address and length of far strings.  Not having access to
  390. that program (insufficient liquid assets), I can't suggest work
  391. arounds (I am sure that there are some library routines that will
  392. give you access).  My guess is that string input will work if the
  393. following format is used
  394.           Inside QBX:
  395.           DECLARE SUB xx(BYVAL SEGADD%, BYVAL OFFADD%, BYVAL
  396. LENGTH%, ...)
  397.           CALL xx(SSEG(A$), SADD(A$), LEN(A$), ...
  398.  
  399.           Inside MASM:
  400.           .code
  401.  
  402.           STRING SEGMENT AT 0h  ;used only for MASM assumptions
  403.           STRING ENDS           ;no code is generated.
  404.  
  405. xx PROC FAR BASIC USES ...,SEGADD:WORD, OFFADD:WORD, LENGTH:WORD
  406.           Push  DS
  407.           ...
  408.  
  409.           Mov   SI,OFFADD       ;offset of string
  410.           Mov   CX,LENGTH       ;length of string
  411.           Mov   AX,SEGADD       ;segment address of far string
  412.                                 ;segment
  413.           Mov   DS,AX
  414.  
  415.           Assume        DS:STRING   ;note lose access to stack
  416. when change DS
  417.           ...
  418.           Pop   DS
  419.           Assume DS:@data
  420.           ...
  421.           Ret
  422.           xx ENDP
  423.           END
  424.           Another approach, which I have not tested is to rely on
  425. the library routines included inside the QBX environment.
  426.  
  427.           Use the following library calls:
  428.           EXTRN StringAddress:FAR
  429.           EXTRN StringLength:FAR
  430.  
  431. How to use StringLength   (must clear direction flag CLD):
  432. Basic program must pass address of string descriptor on stack
  433.  
  434. Push    StringDescriptor  ; push it back on stack
  435. call StringLength         ; call routine
  436. length returned in AX
  437.  
  438. How to use StringAddress (must clear direction flag CLD):
  439. Basic program must pass address of string descriptor on stack
  440.  
  441. Push    StringDescriptor   ; push it back on stack
  442. call StringAddress         ; call routine
  443. address returned in DX:AX  ; DX has segment address, AX has
  444.                            ; offset
  445.  
  446.           QBASIC requires that MASM preserve BP, SI, DI, DS, and
  447. keep the direction flag clear (CLD).  All these routines do this.
  448. You will note that MICROSOFT'S CALL INTERRUPT routines do not
  449. save BP (apparently to give you access to some EGA VGA palette
  450. and character font selection routines in the BIOS), and thus will
  451. crash if a critical error occurs.  MICROSOFT offers a replacement
  452. routine that overcomes this error by preventing any change to BP.
  453. You should get it if you don't already have it.
  454.           The choice of defining MASM routines as SUB's or
  455. FUNCTION's depends on whether you want to get information from
  456. MASM in DX:AX (the format for FUNCTIONs), or if the MASM routine
  457. either sends back no information or more than one variable (the
  458. format for SUBs).  For simple one variable routines when MASM is
  459. just returning a value, use FUNCTIONs.  To use such functions
  460. inside QBASIC you must either assign the value of the function to
  461. a QBASIC variable or use 1) IF ... THEN statements (C style), or
  462. 2) PRINT statements.  For everything else use SUBS.
  463.           Note due to an error in the QBASIC text parser, always
  464. use the CALL keyword to call the library routines if there is any
  465. chance that you will use a colon as a separator on a line AND the
  466. library routine does not take any parameters.  Without the CALL
  467. keyword, the QBASIC parser assumes that the routine name followed
  468. by a colon is intended as a line label, and not as a SUB name.
  469. You must use CALL if you will use a SUB that does not need any
  470. parameters and will follow that SUB name by a colon.
  471.           MASM Theory:
  472.           The MASM routines were designed to be compiled with MS
  473. QUICK ASSEMBLER, using simplified segment names.  They should
  474. compile with MS MASM 5.1 and above.  The DOSSEG keyword might not
  475. be supported by your version of MASM, so use the MASM keyword
  476. that arranges the segments in DOS order, rather than ALPHA order.
  477. If you use TASM with QUIRKS (IDEAL too?) you should be able to
  478. compile these programs with TASM.  Because A86 does not make MS
  479. .OBJ files, you probably cannot use it.  The same may be true
  480. with OPTASM.  The @@, @f, @b are local labels used so I can skip
  481. ahead without having to think up unique names.  Don't use @@, @f,
  482. @b inside MASM Macros, use LOCAL alphanumeric names instead.
  483. MASM too easily can lose track of which local label you mean.
  484.           The simplified directives really save time when you
  485. have to identify variables on the stack, and push and pop
  486. variables.  I use the full PROC function and the regular PROC
  487. keywords interchangeably.  Full PROC format is not necessary when
  488. there is no need to address variables on the stack (i.e. no need
  489. to change BP to address the stack) and the QBASIC routine is
  490. described as a FUNCTION or a SUB that does not take or return
  491. parameters..
  492.           The EVEN directive is used to word align loops for
  493. 80286 and 80386 machines.  EVEN inserts NOPS as necessary to word
  494. align loops.  The QBASIC BYVAL directive is used to get
  495. information directly from QBASIC without having to use [BX] or
  496. [SI] to fish out the correct information.  To allow for
  497. compatibility with the 8088 chip, shifts rather than MULs are
  498. used for speed.  I use .code to store most of my variables to
  499. save space in DGROUP, which is comparatively tiny and easily
  500. filed with string data.
  501.           To program in OS/2 .code segment variables are
  502. "verbotten", and you must use local variables on the stack.  I
  503. don't have access to the OS/2 DOS compatibility box, so I don't
  504. know how these routines would work under OS/2.  I am certain that
  505. none of these routines would work smoothly under protected mode
  506. because they often access the BIOS or the hardware.
  507.  
  508.  
  509. Bibliography:
  510.         General DOS/BIOS routines:  Ray Duncan and Peter Norton's
  511. programming books.  If you can only afford one book, get Duncan's.
  512. Duncan, "Advanced MS-DOS Programming" (2d Ed. Microsoft 1988).  Very
  513. easy to read and to refer to specific routines.  The text is very well
  514. formatted for easy reference.
  515.         Norton, "The New Peter Norton Programmer's Guide to the IBM PC
  516. and PS/2" (Harper & Row 1988).  A book designed to help you visualize
  517. what is going on.  Having been "burned" by writing a book on the PC
  518. Junior, and experienced the agony of hardware incompatibilities in
  519. writing the Norton Utilities, Peter wants everybody to use the bios and
  520. documented DOS routines.
  521.         Bradley, "Assembly Language Programming for the IBM Personal
  522. Computers" (Prentice Hall 1984).  Good technical descriptions of the
  523. original PC.  Only book I have seen that has really shown how to switch
  524. displays, manipulate DMA, make sound, and manipulate floppy disk drives
  525. at the PORT level (teaches you why we have BIOS and DOS routines).  Good
  526. book on the 8087.  Probably now out of print.  I bought my copy at a
  527. book store that sells remainders.
  528.         DOS Programming:
  529.         Detteman, "DOS Programmer's Reference (2d Ed. Que 1989).
  530. Excellent book with a very helpful look at undocumented DOS.  Doesn't
  531. preach about not using undocumented DOS as does Peter Norton.   Goes
  532. "mano a mano" with DOS.  You should read that material for a complete
  533. discussion of the undocumented calls contained in my routines.
  534.         Waite Group "Dos Developer's Guide" (2d Ed Howard Sams 1989).
  535. Good book on Expanded memory and math chips.  Several good discussions
  536. of the undocumented DOS functions.  Such a big book, that you feel you
  537. got your money's worth based just on weight.
  538.         General Programming:
  539.         Holzner, "PS/2-PC Assembly Language"  (Brady 1989)  Good
  540. introduction to assembly language programming.  In many respects much
  541. better than Holzner, "Advanced Assembly Language on the IBM PC" (Brady
  542. 1987).
  543.         Tischer, "PC System Programming for Developers" (ABACUS 1989).
  544. Good technical survey of PC/AT systems.  Comes with a lot of programs
  545. showing how to do useful things in MASM, GWBASIC, PASCAL and C.  The
  546. only shortcoming is that the book is printed on very cheap paper.  One
  547. of the few books to show register usage of DOS and BIOS routines
  548. (important so you can save variables in registers rather than in memory
  549. or pushed on the stack.)  Doesn't discuss DOS Version 4 in an integrated
  550. fashion.  Such a big book, that you feel you got your money's worth
  551. based just on weight.
  552.         Young, "Inside DOS: A Programmer's Guide", (Sybex 1990).  Good
  553. source of MASM code, with a primary emphasis on C (The MASM code is
  554. similar for both C and QBASIC).  A reprint of "MS DOS Advanced
  555. Programming" (Sybex 1988).  (I didn't discover this until I purchased
  556. both).
  557.         Wyatt, "Using Assembly Language" (2d Ed. QUE 1989).  Some decent
  558. video routines.  No useful description of VGA.  EGA routines are
  559. primitive.  Good insight into programming for high level languages.
  560. Complete listing of all the Intel keywords, but reads too much like an
  561. Intel-English dictionary.  Most of the examples in the keyword section
  562. are not really helpful and the ASCII math routines are not well
  563. described.  One major programming feature dropped from the 1st edition
  564. was the AT keyboard programming routines.  Does this mean AT keyboards
  565. are only marginally compatible on the hardware level?  Feedback please.
  566.         QBASIC Programming:
  567.         Goodwin, "QuickBASIC Advanced Programming Tools" (MIS 1989).  A
  568. much better book for QBASIC code (sorting, popup windows, dropdown
  569. windows and menubar programs) than for MASM code.  The MASM code relies
  570. on video bios to do things (which is slow, though always compatible).
  571. Moreover, screens are stored in STRINGs rather than arrays, which
  572. greatly limits the usefulness of his MASM routines.  (I agree storing
  573. screens in arrays takes more work).  A programmer can have access to
  574. several hundred KB of far data in arrays, while he can only have access
  575. to 30 to 40kb of precious string space in DGROUP.  PDS 7.1 gives access
  576. to about 190(?) kb of string space using far strings.  Goodwin's book
  577. was written before PDS was released.
  578.         Lesser,  "Advanced Quickbasic 4.0 Language Extensions with
  579. Modular Tools" (Bantam 1988).  This is how I learned about MASM/QBASIC
  580. programming.  Talks more about ideas that were important for QBASIC
  581. Version 3.0 -- MASM pre-version 5.1  (before simplified directives) than
  582. for QBASIC Version 4.x.  BELIEVES in structured programming.  Not too
  583. many hardware insights even though hardware insights are necessary for
  584. fast video programming.  Offers generally sound advice.
  585.         Microsoft, "QuickBasic Toolbox"  Generally, useful collection of
  586. routines.  Very speedy string routines, some good formatting and a good
  587. set of long int days between dates routines.  Some little insight into
  588. Quick C - Basic interfacting using Quick C library routines.  The DOS
  589. InterruptX routines are generally useful, however, they do not warn of a
  590. problem inside QBASIC that can cause QBASIC to lock up.  The error
  591. occurs if a critical error (typically disk error) occurs inside a Call
  592. Interrupt/InterruptX routine.
  593.         Reason for error: Because the Microsoft supplied version of that
  594. routine allows the programmer to change BP, any critical error causes
  595. QBASIC to get lost.  All smart programmers should obtain, from
  596. Microsoft's on-line knowledgebase on GENIE and COMPUSERVE, a copy of the
  597. revised routine and NOCOM.OBJ (makes some programs smaller by turning
  598. off all of QBASIC overhead associated with the COM ports) from
  599. Microsoft.  The revised Interrupt/InterruptX routines prevents any
  600. change to BP at the cost of a minor loss of funtionality in EGA/VGA font
  601. routines.
  602.         Shammas, "QuickBASIC- Programming Techniques and Library
  603. Development" (M&T Publishing 1988).  Good QBASIC code.  Some of the
  604. string routines are fast.  He has some BTREE and high level math
  605.  
  606. What's available:
  607.         VIDBASIC - A selection of text mode video routines.  Freeware.
  608. The library allows the user to select, move, switch, change, save,
  609. restore, draw boxes, and write with lightening speed.  MASM .ASM code,
  610. .OBJ, and a demo routine with source is included.  Uploaded by author on
  611. GENIE and COMPUSERVE.
  612.         KEYBASIC - A selection of Microsoft Compatible Mouse and
  613. Keyboard utilities.  Text mode mouse utilities.  Fast mouse utilities.
  614. Turn off CONTROL-BREAK so you can use LINE INPUT$ without error if user
  615. pushes the Control-Break key.  Freeware. MASM .ASM code, .OBJ, and a
  616. demo routine with source is included.  Uploaded by author on GENIE and
  617. COMPUSERVE.
  618.  
  619.         I don't anticipate I will do much more with any of these three
  620. libraries.  My next effort is to make menu environment similar to the
  621. environment inside QuickBasic, using the building blocks I have created.
  622. After that, I will probably try to figure out Quick C and convert much
  623. of the library to Quick C format.  I figure by the time I begin to
  624. understand Quick C, an OOPS form of Quick Basic will come out and much
  625. of my work will be for naught.
  626.         As always, constructive criticism is desired.  These libraries
  627. were released as Freeware to encourage a sharing of ideas.  If you have
  628. something to say, I welcome your comments.  With application programs
  629. there appears to be a significant and speedy exchange of ideas,
  630. programmers, on the other hand, seem to move at a much slower pace, with
  631. Jim Mack being the notable exception.
  632.