home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l352 / 1.img / DOC / LITE286.DOC < prev    next >
Encoding:
Text File  |  1992-06-04  |  83.5 KB  |  2,155 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.                                Borland C++
  11.                    User's Guide to 286|DOS-Extender Lite
  12.  
  13.                          Phar Lap Software, Inc.
  14.                 60 Aberdeen Ave., Cambridge, MA  02138
  15.                             (617) 661-1510
  16.                           FAX (617) 876-2972
  17.                        tech-support@pharlap.com
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45. Copyright (c) 1992 Phar Lap Software, Inc.
  46.  
  47. All rights reserved.  Printed in the United States of America.  No 
  48. part of this publication may be reproduced, stored in a retrieval 
  49. system, or transmitted in any form or by any means, without prior 
  50. written permission of Phar Lap Software, Inc.  Use, duplication, or 
  51. disclosure by the Government is subject to restrictions as set forth 
  52. in subparagraph (c)(1)(ii) of the Rights in Technical Data and 
  53. Computer Software clause at 252.227-7013.
  54.  
  55.  
  56.  
  57.              Outline of Contents
  58.  
  59. Introduction           
  60.  
  61. Chapter 1    A Quick Tour of 286|DOS-Extender Lite
  62.   Big Malloc
  63.   Protected Mode C++
  64.   Protected Mode MS-DOS
  65.   BIOS Calls in Protected Mode
  66.   Compatibility with Industry Standards
  67.   What's So Protected About Protected Mode?
  68.   Debugging with TDW Under MS-DOS (with the 286|DOS-Extender Software
  69.       Development Kit)
  70.   What About Direct Screen Writes?
  71.   Summary
  72.  
  73. Chapter 2    Using 286|DOS-Extender Lite with Borland C++
  74.   BCC286 Usage in Detail
  75.     BCC286 Input Files
  76.     Environment Variable
  77.   BCC286 Switches
  78.     -keep
  79.     -nostub
  80.     -stack=xxx
  81.   BCC286 Differences from BCC
  82.   Using BCC and TLINK
  83.     BCC Switches
  84.     .DEF File Statements
  85.     TLINK Switches and Files
  86.   Building Floating-Point Programs
  87.  
  88. Chapter 3    Running Protected Mode Applications Under MS-DOS
  89.   Compatibility
  90.   LITE286 Requirements
  91.   Error Messages
  92.   LITE286 Command Line Options
  93.   The Phar Lap Application Program Interface (PHAPI)
  94.  
  95. Chapter 4    Run-Time Library
  96.  
  97. Further Reading
  98.  
  99.  
  100. ------------
  101. Introduction
  102. ------------
  103.  
  104. Welcome to the world beyond 640K!
  105.  
  106. Now, with your FREE 286|DOS-Extender Lite, it's easy to build multi-
  107. megabyte Borland C++ programs!  286|DOS-Extender Lite is a special 
  108. Borland C++ version of Phar Lap Software's award-winning 286|DOS-
  109. Extender Software Development Kit (SDK).  It enables your program to 
  110. break the 640K DOS barrier and access up to 2 MB of memory, with no 
  111. need for overlays or EMS.  Your Extended-DOS programs will run under 
  112. DOS, DESQview and Windows.
  113.                                 
  114. 286|DOS-Extender Lite includes all the capabilities you need to build 
  115. and run Extended-DOS programs with Borland C++.  However, you may want 
  116. to purchase Phar Lap's 286|DOS-Extender SDK if you would like the 
  117. following features:  Turbo Debugger support, access to up to 16 MB of 
  118. memory, Phar Lap's technical support and extensive documentation, and 
  119. the ability to deliver your Extended-DOS application to customers with 
  120. Phar Lap's 286|DOS-Extender Run-Time Kit (RTK).  The following chart 
  121. outlines the differences between 286|DOS-Extender Lite and 286|DOS-
  122. Extender SDK.  To order your SDK, just fill out the following coupon 
  123. or contact Phar Lap.
  124.  
  125. 286|DOS-Extender SDK is available from:    Phar Lap Software, Inc.
  126.                                            60 Aberdeen Avenue
  127.      FREE PHAR LAP T-SHIRT               Cambridge, MA  02138
  128.        WITH EVERY ORDER!                 Phone 617-661-1510
  129.                                            Fax 617-876-2972
  130.  
  131.              286|DOS-EXTENDER LITE VS 286|DOS-EXTENDER SDK
  132.  
  133. 286|DOS-Extender Lite               │    286|DOS-Extender SDK
  134. ════════════════════════════════════╪═════════════════════════════════════
  135. No debugging support                │  Full support for Turbo Debugger
  136.                                     │
  137. Programs can use up to 2 MB memory  │  Programs can use up to 16 MB memory
  138.                                     │
  139. 50 pages of documentation on disk   │  700+ pages of printed documentation
  140.                                     │
  141. Technical support for installation  │  Technical support for development
  142.                                     │
  143. Cannot deliver Extended-DOS         │  Add-on run-time kit available for
  144.   programs to customers             │    delivering Extended-DOS programs
  145.                                     │
  146. Several example programs            │  Extensive example programs
  147.                                     │
  148. No spawn function available         │  Supports spawn function to run
  149.                                     │    protected mode or real mode .EXEs
  150.                                     │
  151. May be used with Borland C++ only   │  May be used with other compilers
  152.                                     │
  153. Available FREE with Borland C++     │  Available for $495 from Phar Lap
  154.  
  155.  
  156.                      286|DOS-Extender Order Form
  157.  
  158.  
  159. YES!  I would like to order ____ 286|DOS-Extender SDK x $495 each = _______
  160.       Mass. customers add 5% sales tax:                             _______
  161.       Shipping:  $5 U.S. or Canada, $50 overseas:                   _______
  162.       TOTAL =                                                       _______
  163.  
  164. Shipping Address:  (Please provide a street address.  No P.O. boxes.)
  165.       Name:__________________________ Company:_____________________________
  166.       Address:_____________________________________________________________
  167.       City:__________________________ State/Country:__________ Zip:________
  168.       Phone:_________________________ Fax:_________________________________
  169.  
  170. Method of Payment: (Check one)
  171.       ____ Check/money order (US$, US bank)    
  172.       ____ P.O.#(Approval required):_______________________________________
  173.       ____ MasterCard     ____ Visa     ____ American Express
  174.       Credit Card #:__________________________________ Exp. Date:__________
  175.       Cardholder's name:___________________________________________________
  176.  
  177. Return to:  Phar Lap Software, Inc.           FREE PHAR LAP T-SHIRT 
  178.             60 Aberdeen Avenue                  WITH EVERY ORDER!   
  179.             Cambridge, MA  02138
  180.             Phone 617-661-1510
  181.             Fax 617-876-2972
  182.  
  183.  
  184. -------------------------------------
  185. Chapter 1
  186. A Quick Tour of 286|DOS-Extender Lite
  187. -------------------------------------
  188.  
  189.  
  190.    Computers with Intel and Intel-compatible 80286, 80386, or 80486 
  191. microprocessors hold a majority share of the IBM PC-compatible 
  192. marketplace.  These machines typically have two or more megabytes of 
  193. memory.  This is in sharp contrast to the situation just a few years 
  194. ago, when the typical PC had an 8088 and less than a megabyte of 
  195. memory.
  196.  
  197.    But MS-DOS has not kept up with these sweeping changes.  While PCs 
  198. are shipping with more memory and better processors, more DOS 
  199. applications than ever run out of memory.
  200.  
  201.    Many users have found that a 2 MB machine, for example, does not 
  202. actually give their applications 2 MB of memory:  applications are 
  203. held back by the 640K limitation imposed by MS-DOS.  You can add 
  204. memory to an IBM AT, PS/2, or 386 clone until you're blue in the 
  205. face, and many DOS applications will nonetheless run out of memory.
  206.  
  207.    These machines have untapped resources.  286|DOS-Extender Lite, Phar 
  208. Lap's 16-bit DOS extender for 80286, 80386, and 80486 PCs, puts all 
  209. this potential energy to work while fully preserving your investments 
  210. in MS-DOS and Borland C++.
  211.  
  212.    Let's look at an example.  Many manuals begin with the "hello 
  213. world" sample program, but to show the power of 286|DOS-Extender Lite 
  214. we need a sample program that suffers from the 640K confines of MS-
  215. DOS.  Such programs are plentiful; almost any DOS program that uses 
  216. large model, huge model, overlays, expanded memory (EMS), or the 
  217. eXtended Memory Specification (XMS), is a good example.  Any such 
  218. program is also a likely candidate for using 286|DOS-Extender Lite!
  219.  
  220.    But short of including 50,000 lines of code in our manual, how can 
  221. we provide a quick look at the problem of running old DOS on the new 
  222. machines?
  223.  
  224.    We can simulate some "programming in the large" issues by using a 
  225. small C program that requires a large amount of memory.  The program 
  226. shown below, BIG.C, attempts to use one megabyte of memory by 
  227. declaring a 512 x 512 two-dimensional array of longs:
  228.  
  229. /* BIG.C */
  230.  
  231. #include <stdlib.h>
  232. #include <stdio.h>
  233.  
  234. #define SIZE    512
  235.  
  236. static long huge array[SIZE][SIZE] ;  /* one-megabyte array */
  237.  
  238. main()
  239. {
  240.     int i, j;
  241.  
  242.     printf("Using %lu-byte array\n", 
  243.     (long) SIZE * SIZE * sizeof(long));
  244.  
  245.     for (i=0; i<SIZE; i++)
  246.     {
  247.     for (j=0; j<SIZE; j++)
  248.         array[i][j] = (long) i * j; /* touch every element */
  249.     printf("%d\r", i);              /* display odometer */
  250.     }
  251.  
  252.     printf("done\n");
  253.     return 0;
  254. }
  255.  
  256.    The Borland C++ command-line compiler, BCC, can be used to compile 
  257. and link this straightforward C program for plain-vanilla, real mode 
  258. MS-DOS.  The -ml (large model) switch is used in the BCC command line 
  259. to get the maximum amount of available memory:
  260.  
  261. C:\>bcc -ml big.c
  262.  
  263.    While BCC compiles BIG.C without error, the Borland linker, TLINK, 
  264. refuses to link the program, and produces the following error 
  265. message:
  266.  
  267. Fatal: Relocation item exceeds 1Meg DOS limit.
  268.  
  269.    This isn't a problem with TLINK, because the Microsoft linker has 
  270. the same limitation (though it doesn't produce as clear an error 
  271. message as TLINK does).  The problem is that real mode MS-DOS really 
  272. does have a one-megabyte barrier!  Even if TLINK did somehow produce 
  273. BIG.EXE, it wouldn't run properly under real mode MS-DOS.
  274.  
  275.    But to run BIG.EXE you don't have to switch to a different 
  276. operating system.  286|DOS-Extender Lite removes the one-megabyte DOS 
  277. barrier, while continuing to run under DOS.  You get to have your cake
  278. and eat it too.
  279.  
  280.    To produce a 286|DOS-Extender Lite version of the BIG program, 
  281. simply compile and link with BCC286, which is one of the programs 
  282. included with 286|DOS-Extender Lite.  BCC286 runs BCC and TLINK, 
  283. taking care of all the details of producing a protected mode 
  284. executable.  Protected mode executable?  Under DOS?  That's right:
  285.  
  286. C:\>bcc286 big.c
  287.  
  288. C:\>big
  289. Using 1048576-byte array
  290. done
  291.  
  292.    We just allocated and accessed one megabyte under MS-DOS, in a 
  293. program whose name we typed on the DOS command line -- just like any 
  294. other regular DOS program.  The source code for the program, as we've 
  295. seen, used absolutely standard PC constructs:  no messing with 
  296. special interfaces like EMS or XMS, and no overlays.
  297.  
  298.    It's as if MS-DOS had been turned into a protected mode operating 
  299. system, or at least into an operating system that can run protected 
  300. mode programs!  This in fact is exactly what 286|DOS-Extender Lite 
  301. does.  Behind the scenes, when BIG is run from the DOS command line, 
  302. the program reinvokes itself under 286|DOS-Extender Lite, which 
  303. resides in a program named LITE286.EXE (which, incidentally, must be 
  304. somewhere on the path along with another file, called DOSCALLS.DLL).  
  305. Running BIG is equivalent to running LITE286 BIG.  LITE286 puts the 
  306. machine into protected mode, runs BIG, then puts the machine back 
  307. into real mode.
  308.  
  309.    Clearly, BIG is not a typical real mode DOS program.  BCC286 takes 
  310. advantage of TLINK's ability to produce protected mode Windows 
  311. programs, using it instead to produce protected mode DOS programs.  
  312. Chapter 2 of this manual explains precisely how BCC286 runs BCC and 
  313. TLINK, so that if you prefer, you can run BCC and TLINK yourself 
  314. (from MAKE, for example) rather than use BCC286.
  315.  
  316. ----------
  317. Big Malloc
  318. ----------
  319.  
  320.    The huge array used in BIG.C provides a simple first example of 
  321. 286|DOS-Extender Lite.  In the same way that LITE286 can load a 
  322. program with large amounts of data, it can also load programs with 
  323. large amounts of code, so the huge array is a good simulation of a 
  324. large program.  Most C programs do not create huge static arrays, but 
  325. many DOS programs do contain enormous amounts of code.  Such programs 
  326. often resort to performance-crippling overlays; BIG shows that, on an 
  327. 80286 or higher machine with extended memory, this workaround is not 
  328. necessary.
  329.  
  330.    BIG.C made life easy for itself by using the "huge" keyword, but 
  331. due to its often poor performance, "huge" is usually avoided in 
  332. commercial PC software.  (On the other hand, BCC286 automatically 
  333. uses the BCC -h option for "fast" huge pointers.) More typically, 
  334. large PC applications dynamically allocate memory via the C malloc() 
  335. function, via operator new in C++, or directly via the MS-DOS 
  336. Allocate Memory Block function (INT 21h AH=48h).
  337.  
  338.    Our next example program, MEMTEST, does nothing more than run 
  339. malloc() in a loop and touch every byte of the allocated memory.  
  340. When malloc() eventually returns NULL, indicating that memory is 
  341. exhausted, MEMTEST breaks out of the loop.  While clearly the program 
  342. does not do anything useful with the memory it allocates, its 
  343. insatiable appetite for memory is a very good simulation of a large 
  344. application:
  345.  
  346. /* MEMTEST.C */
  347.  
  348. #include <stdlib.h>
  349. #include <stdio.h>
  350.  
  351. main()
  352. {
  353.     char *p;
  354.     unsigned long allocs;
  355.  
  356.     for (allocs = 0; ; allocs++)
  357.        if ((p = malloc(1024)) != 0)    /* in 1k blocks */
  358.        {
  359.        memset(p, 0, 1024); /* touch every byte */
  360.        *p = 'x';           /* do something, anything with */
  361.        p[1023] = 'y';      /* the allocated memory      */
  362.             
  363.        if (allocs && (allocs % 1024) == 0)   /* odometer */
  364.            printf("Allocated %u megabytes\r", allocs >> 10);
  365.        }
  366.        else
  367.        break;
  368.  
  369.        printf("Allocated %lu bytes\n", allocs << 10);
  370.        return 0;
  371. }
  372.  
  373.    Using Borland C++ 3.1, this program can be compiled for real mode 
  374. MS-DOS with the following command line:
  375.  
  376. C:\>bcc -ml memtest.c
  377.  
  378.    This produces a large model version of MEMTEST.EXE, allowing 
  379. maximum memory allocation under real mode MS-DOS.  On a COMPAQ 386 
  380. with 2 MB of memory, MEMTEST should allocate around 2 MB of 
  381. memory (if you don't think this is what MEMTEST should do, you've 
  382. been programming in real mode for too long!).  But of course, here is 
  383. what real mode large model MEMTEST does instead:  
  384.  
  385. C:\>memtest
  386. Allocated 417792 bytes
  387.  
  388.    Only 408 KB available on a 2 MB machine?!  By making better use  
  389. of the DOS 5.0 LOADHIGH, DEVICEHIGH, and DOS=HIGH,UMB statements, or 
  390. by using superb expanded memory managers such as Quarterdeck QEMM or 
  391. Qualitas 386MAX, we could probably have created a better 
  392. configuration, in which MEMTEST might get as much as 610 KB or so.  
  393. But no matter how much we huffed and puffed and fooled with 
  394. CONFIG.SYS, real mode MEMTEST would never allocate more than one 
  395. megabyte of memory.
  396.  
  397.    Furthermore, even if you do maximize the available DOS memory on 
  398. one machine, there is no guarantee that all (or even most) of a 
  399. program's users will have such an "ideal" configuration.  By 
  400. developing for protected mode DOS, you can bypass a lot of these 
  401. messy user-configuration issues.
  402.  
  403.    Now, to produce a version of MEMTEST that behaves more sensibly, 
  404. the only thing you need to remember is BCC286:
  405.  
  406. C:\>bcc286 memtest.c
  407.  
  408. C:\>memtest
  409. Allocated 2193408 bytes
  410.  
  411.    We allocated almost 2 MB of memory under MS-DOS!  This is 
  412. dramatically different behavior from the first version of MEMTEST we 
  413. produced, yet we're using the same source code as before.  Simply by 
  414. recompiling for 286|DOS-Extender Lite, without source code changes, 
  415. we have a program that runs under DOS yet breaks the 640K barrier, 
  416. without EMS, overlays, or other workarounds.  Simply by using 
  417. 286|DOS-Extender Lite with Borland C++, you get a version of malloc() 
  418. that transparently uses extended memory, and functions such as 
  419. memset(), and pointer dereferences such as *p and p[1023], that 
  420. transparently access extended memory.
  421.  
  422. ------------------
  423. Protected Mode C++
  424. ------------------
  425.  
  426.    286|DOS-Extender Lite is not limited to programs written in C; C++ 
  427. programs can just as easily run under protected mode DOS.  For 
  428. example, the C++ new operator in protected mode DOS works exactly the 
  429. same as the C malloc() function:  instead of halting somewhere 
  430. around 640K, operator new can be used to allocate up to 2 MB of 
  431. memory under 286|DOS-Extender Lite.  (286|DOS-Extender SDK can 
  432. allocate up to 16 MB.)
  433.  
  434.    Other C++ features, such as the iostream input and output 
  435. operators and static constructors and destructors, work just the way 
  436. one would expect from having used C++ in real mode DOS.
  437.  
  438.    The next sample program, MEMTEST2.CPP, uses a number of C++ 
  439. features.  The C++ set_new_handler() function is particularly useful; 
  440. it lets MEMTEST2 install a handler that will automatically be called 
  441. when operator new fails.  This considerably simplifies the program's 
  442. main loop:  
  443.  
  444. /* MEMTEST2.CPP */
  445.  
  446. #include <stdlib.h>
  447. #include <iostream.h>
  448. #include <new.h>
  449.  
  450. class msg {
  451. public:
  452.     msg()   { cout << "hello from " << __FILE__ << "\n" ; }
  453.     ~msg()  { cout << "bye\n" ; }
  454.     } ;
  455.  
  456. static msg banner;  // test C++ static constructors, destructors
  457.  
  458. static unsigned long bytes = 0;
  459. static unsigned long allocs = 0;
  460. static unsigned blk_size = 10240;
  461.  
  462. void new_fail(void)
  463. {
  464.     if (blk_size)
  465.     blk_size >>= 1;  // try to allocate a smaller block
  466.     else
  467.     {   // memory exhausted
  468.     cout << "Allocated " << bytes << " bytes\n" ;
  469.     exit(1);
  470.     }
  471. }
  472.  
  473. main()
  474. {
  475.     char *p;
  476.  
  477.     set_new_handler(new_fail);   // called when new fails
  478.  
  479.     for (;;)
  480.     {
  481.        p = new char[blk_size];   // allocate memory
  482.        memset(p, 0, blk_size);   // touch every byte
  483.        *p = 'x';                 // do something, anything with
  484.        p[blk_size-1] = 'y';      //   the allocated memory
  485.             
  486.        bytes += blk_size;
  487.        allocs++;
  488.        if ((allocs % 25) == 0)   // odometer
  489.         cout << "Allocated " << bytes << " bytes\r";
  490.     }
  491. }
  492.  
  493.    We won't even bother showing the real mode version this time, 
  494. since by now it's pretty obvious how limited real mode is.  To 
  495. compile this C++ program for protected mode DOS, all you need is 
  496. BCC286:
  497.  
  498. C:\>bcc286 memtest2.cpp
  499.  
  500. C:\>memtest2
  501. hello from memtest2.cpp
  502. Allocated 2027520 bytes
  503. bye
  504.  
  505.    Because 286|DOS-Extender Lite is compatible with the DPMI 
  506. specification (as well as with every other major memory-management 
  507. specification, including VCPI, XMS, VDS, and INT 15h), this protected 
  508. mode C++ program can allocate up to 2 MB of memory under all modes of 
  509. Windows 3.x:
  510.  
  511. C:\>memtest2
  512. hello from memtest2.cpp
  513. Allocated 2027520 bytes
  514. bye
  515.  
  516. ---------------------
  517. Protected Mode MS-DOS
  518. ---------------------
  519.  
  520.    What's really happening here?  We've seen that 286|DOS-Extender 
  521. Lite can load programs with huge arrays, or enormous amounts of code, 
  522. and that protected mode DOS versions of C functions such as malloc(), 
  523. and of operator new in C++, can dynamically allocate large amounts of 
  524. memory.  How does all this work?
  525.  
  526.    While generally used with C or C++ programs, 286|DOS-Extender Lite 
  527. is not a C or C++ library.  286|DOS-Extender Lite does replace some 
  528. of the Borland C++ startup code and library functions, but this is 
  529. simply to make the code protected mode "clean." The real magic occurs 
  530. at a lower level.
  531.  
  532.    In essence, 286|DOS-Extender Lite provides MS-DOS (INT 21h) 
  533. functions in protected mode.  Since your program runs in protected 
  534. mode, any software interrupts your program generates -- such as DOS  
  535. calls made by the C run-time library when you call a function such as 
  536. printf() -- occur in protected mode too, and are caught by 286|DOS-
  537. Extender Lite. 
  538.  
  539.    In most cases, 286|DOS-Extender Lite passes the call down to MS-
  540. DOS, which is still running in real mode.  DOS file I/O functions are 
  541. handled this way, for example:  the 286|DOS-Extender Lite handler for 
  542. these functions reissues (or "reflects") the call in real mode. 
  543.  
  544.    Merely by providing protected mode surrogates for these functions, 
  545. 286|DOS-Extender Lite allows your program to think that it is running 
  546. under a protected mode version of MS-DOS.  The program can call INT 
  547. 21h in protected mode without worrying about the fact that its file 
  548. I/O buffers are probably located in extended memory.  286|DOS-
  549. Extender Lite automatically takes care of all the details of 
  550. transferring data between conventional memory (where real mode DOS 
  551. can get at it) and extended memory (where your protected mode program 
  552. probably allocated it).
  553.  
  554.    Because 286|DOS-Extender Lite acts as a protected mode "wrapper" 
  555. around real mode MS-DOS, you have a completely compatible 
  556. environment.  286|DOS-Extender Lite isn't replacing DOS, so it will 
  557. work with whatever version of DOS you or your customers already have.
  558.  
  559.    Of course, real mode MS-DOS does not know how to do things like 
  560. run protected mode programs, allocate extended memory, load dynamic 
  561. link libraries (DLLs), or install protected mode interrupt handlers.  
  562. Requests such as these are handled by 286|DOS-Extender Lite entirely 
  563. in protected mode.
  564.  
  565.    Memory allocation is a good example.  Rather than use C or C++ 
  566. constructs to allocate memory, the next sample program, DOSMEM.C, 
  567. goes directly to DOS using INT 21h Function 48h (Allocate Memory 
  568. Block).  Typically, a DOS program finds out how much memory is 
  569. available by asking this function for 0FFFFh paragraphs (one 
  570. megabyte).  Real mode DOS will naturally fail such a request, but it 
  571. will also return the actual number of paragraphs available in the 
  572. largest block of free memory:
  573.  
  574. /*  DOSMEM.C */
  575.  
  576. #include <stdlib.h>
  577. #include <stdio.h>
  578. #include <dos.h>
  579.  
  580. main()
  581. {
  582.     unsigned segment, avail;
  583.     char far *fp;
  584.     _asm mov ah, 48h
  585.     _asm mov bx, 0FFFFh
  586.     _asm int 21h
  587.     _asm jc error
  588.     _asm mov segment, ax
  589.     fp = MK_FP(segment, 0);
  590.     *fp = 'x';   /* make sure it's genuine */
  591.     printf("Allocated 0FFFFh paragraphs: %Fp\n", fp);
  592.     return 0;
  593. error:
  594.     _asm mov avail, bx
  595.     printf("Only %04Xh paragraphs available\n", avail);
  596.     return 1;
  597. }
  598.  
  599. C:\>bcc dosmem.c
  600.  
  601. C:\>dosmem
  602. Only 4FE9 paragraphs available
  603.  
  604. In protected mode, an amazing thing happens:  a request for 0FFFFh 
  605. paragraphs easily succeeds:
  606.  
  607. C:\>bcc286 dosmem.c
  608.  
  609. C:\>dosmem
  610. Allocated 0FFFFh paragraphs: 0A3D:0000
  611.  
  612.    Using the exact same INT 21h functional interface as real mode 
  613. DOS, 286|DOS-Extender Lite provides functionality that DOS alone 
  614. can't provide.  This new functionality is provided to every protected 
  615. mode program running under 286|DOS-Extender Lite.  Thus, 286|DOS-
  616. Extender Lite isn't a library, but an extension to the operating 
  617. system.  (That's why it's called a DOS extender.)
  618.  
  619.    When protected mode DOSMEM allocates 0FFFFh paragraphs, where does 
  620. this memory come from?  In general, this doesn't matter to the 
  621. program, because it has asked INT 21h Function 48h for memory, and 
  622. has received a value back in the AX register which it can use as the 
  623. basis for a far segment:offset pointer.  In DOSMEM.C, note how a far 
  624. pointer is created with the Borland MK_FP() macro, and poked with the 
  625. C * dereferencing operator.  Thus, we have immediately usable memory; 
  626. it doesn't really matter where it "comes from," nor for that matter 
  627. what value INT 21h Function 48h returns in AX.  All we need to know 
  628. is that we can use it.
  629.  
  630.    However, the pointer 0A3D:0000 displayed above by DOSMEM in 
  631. protected mode is a little strange.  Paragraph 0A3Dh seems to be too 
  632. low in memory, for example.  But in protected mode the address 
  633. 0A3D:0000 has nothing whatever to do with absolute memory location 
  634. 0A3D0h.  Instead, 0A3Dh is a protected mode selector that is 
  635. essentially an index into a table of segment descriptors used by the 
  636. chip.  These descriptors in turn contain the base address, size, and 
  637. protection "access rights" of the corresponding segment.  Thus, 
  638. memory management in protected mode is somewhat indirect, but all the 
  639. indirection is managed entirely by the chip, "inside" an instruction 
  640. such as MOV AX, ES:[BX].
  641.  
  642. ----------------------------
  643. BIOS Calls in Protected Mode
  644. ----------------------------
  645.  
  646.    To create a useful environment for PC software, it is not 
  647. sufficient merely to provide INT 21h in protected mode.  The ROM BIOS 
  648. calls (INT 10h, INT 16h, and so on) need to be available in protected 
  649. mode too. 
  650.  
  651.    Borland C++ run-time library functions such as bioscom(), 
  652. biosprint(), and bioskey() are available in protected mode.  
  653. Furthermore, protected mode DOS programs can call BIOS functions from 
  654. separate .ASM modules assembled with Turbo Assembler (TASM), or using 
  655. inline assembler, the int86() and int86x() functions, or Borland 
  656. register pseudovariables.
  657.  
  658.    For example, if our MEM sample program did direct screen writes 
  659. (which we will discuss in more detail later in this chapter), it 
  660. might include initialization code such as the following, which uses 
  661. INT 10h Function 0Fh (Get Video Mode):
  662.  
  663. #include <dos.h>
  664.  
  665. #define GET_VIDEO_MODE      0x0F
  666.  
  667. int video_mode(void)
  668. {
  669.     union REGS r;
  670.     r.h.ah = GET_VIDEO_MODE;
  671.     int86(0x10, &r, &r);
  672.     return r.h.al;
  673. }
  674.  
  675. or, using inline assembler, something like this:
  676.  
  677. int video_mode(void)
  678. {
  679.     _asm mov ah, GET_VIDEO_MODE
  680.     _asm int 10h
  681.     _asm xor ah, ah
  682.     // 2 byte quantity returned in AX
  683. }
  684.  
  685. or, using Borland register pseudovariables:
  686.  
  687. int video_mode(void)
  688. {
  689.     _AH = GET_VIDEO_MODE;
  690.     geninterrupt(0x10);
  691.     _AH = 0;
  692.     // 2 byte quantity returned in AX
  693. }
  694.  
  695.    All these varieties of the video_mode() function run just fine in 
  696. protected mode, because 286|DOS-Extender Lite supports INT 10h (BIOS 
  697. Video) in protected mode.
  698.  
  699.    The following list shows all interrupts and functions that are 
  700. supported in protected mode -- the vast majority of DOS (INT 21h) 
  701. and BIOS (INT 10h, INT 16h, etc.) calls: 
  702.  
  703. INT 10h (BIOS Video)      
  704.   Functions 0 through 1Ch 
  705.  
  706. INT 11h (BIOS Equipment Check)
  707.  
  708. INT 12h (Conventional Memory Size) 
  709.  
  710. INT 14h (BIOS Communications)
  711.   Functions 0 through 5  
  712.  
  713. INT 16h (BIOS Keyboard)
  714.   Functions 0 through 12h 
  715.  
  716. INT 17h (BIOS Printer)
  717.   Functions 0 through 2  
  718.  
  719. INT 1Ah (BIOS Time)
  720.   Functions 0 through 80h
  721.  
  722. INT 21h (MS-DOS Functions)
  723.   Functions 0 through 0Eh
  724.   Functions 19h through 30h
  725.   Functions 32h through 43h
  726.   Function 44h (IOCTL)
  727.     Subfunctions 0, 1, 6, 7, 8, 9, 0Ah, 0Bh, 0Eh, and 0Fh
  728.   Functions 45h through 63h
  729.     Because a request to INT 21h Function 48h (Allocate Memory Block)
  730.     for FFFFh paragraphs can succeed in protected mode, this function 
  731.     should be used only for memory allocation, not to determine the 
  732.     amount of available memory.  Use the DosMemAvail() and DosRealAvail() 
  733.     functions instead for this purpose.
  734.   Functions 66h through 6Ch
  735.  
  736. INT 33h (Microsoft Mouse)
  737.  
  738. -------------------------------------
  739. Compatibility with Industry Standards
  740. -------------------------------------
  741.  
  742.    We have seen that 286|DOS-Extender Lite (that is, LITE286.EXE) 
  743. manages the interface between your protected mode program and real 
  744. mode MS-DOS.  At the DOS command line, when you type the name of a 
  745. protected mode .EXE file, LITE286 puts the machine into protected 
  746. mode and launches your program.  Whenever your program makes DOS or 
  747. BIOS calls from protected mode, 286|DOS-Extender Lite handles them 
  748. and/or passes them down to MS-DOS or the ROM BIOS.  When your program 
  749. exits, 286|DOS-Extender Lite puts the computer back into real mode.
  750.  
  751.    But what if the machine wasn't in real mode to begin with?  Many 
  752. 80386 and 80486 computers, for example, will be running software such 
  753. as Microsoft Windows 3.x (Enhanced mode), Microsoft EMM386, 
  754. Quarterdeck DESQview/386, or Qualitas 386MAX.  When these are loaded, 
  755. MS-DOS is running not in real mode but in a one-megabyte protected 
  756. mode that Intel calls "virtual 8086" mode.  Furthermore, users may be 
  757. running programs that use extended memory, such as VDISK, HIMEM, or 
  758. SMARTDrive.
  759.  
  760.    286|DOS-Extender Lite handles all these situations gracefully.  It 
  761. is compatible with all the PC industry standards for protected mode, 
  762. expanded memory (EMS), and extended memory (XMS).  It supports the 
  763. Virtual Control Program Interface (VCPI) and DOS Protected Mode 
  764. Interface (DPMI).  VCPI, a specification developed jointly by 
  765. Quarterdeck Office Systems and Phar Lap Software, allows EMS 
  766. emulators and DOS extenders to coexist; it is an extension to EMS 
  767. 4.0.  DPMI is a specification whose primary goal is compatibility 
  768. between DOS extenders and DOS multitasking environments; DPMI was 
  769. jointly developed by a committee including Microsoft, Intel, IBM, 
  770. Phar Lap, Quarterdeck, Borland, Lotus, Rational Systems, and other 
  771. companies.  
  772.  
  773.    This means that programs developed with 286|DOS-Extender Lite can 
  774. run in a wide variety of DOS environments.
  775.  
  776.    All this compatibility requires no work from you.  There is no 
  777. configuration or "tune" program to run.  286|DOS-Extender Lite 
  778. automatically configures itself each time it runs.  If run under 
  779. Windows 3.x Enhanced mode, for example, the program will 
  780. automatically get virtual memory with no additional effort.  Or if 
  781. you switch from HIMEM.SYS to QEMM386.SYS, you don't have to 
  782. reconfigure 286|DOS-Extender Lite in any way.  
  783.  
  784. -----------------------------------------
  785. What's So Protected About Protected Mode?
  786. -----------------------------------------
  787.  
  788.    So far we have described the process of compiling for protected 
  789. mode and running under MS-DOS.  The next step in the development 
  790. cycle is debugging.
  791.  
  792.    Returning to the MEM sample program, for example, suppose we 
  793. forgot to check the return value from malloc().  In the C++ version, 
  794. we could use set_new_handler() to catch failed memory allocations.  
  795. But in C, it's simply a mistake to forget to check the return value 
  796. from malloc():
  797.  
  798. for (allocs = 0; ; allocs++)
  799. {
  800.    p = malloc(1024);
  801.    /* BUG:  not checking return value from malloc!*/
  802.    memset(p, 0, 1024);
  803.    *p = 'x';
  804.    p[1023] = 'y';
  805. }
  806.  
  807.    This horrible code runs without complaint in real mode.  In a 
  808. large model program, its probable effect is to repeatedly bash the 
  809. low-memory interrupt vector table.
  810.  
  811.    What happens in protected mode when malloc() fails and we then try 
  812. to dereference (peek or poke) the resulting NULL pointer?  Instead of 
  813. trashing memory, the program halts with a message like this:
  814.  
  815. Fatal error 286.3330: General protection fault detected.
  816. PID=0001  TID=0001  SID=0001  ERRORCODE=0000
  817. AX=0000  BX=0000  CX=0200  DX=0000  SI=056C  DI=0000  BP=2DCC
  818. CS:IP=014F:0CC5   DS=0157  ES=0000  SS:SP=0157:2DCA   FLAGS=3216
  819.  
  820.    The message "General protection fault detected" is an indication 
  821. that the program has in some way violated the rules of protected 
  822. mode.  These rules prevent writing into code segments, executing data 
  823. segments, reading or writing past the end of a segment, or using a 
  824. segment that doesn't belong to you.  
  825.  
  826.    A general protection violation, or GP fault, shows either a bug in 
  827. your program, or an area that needs to be converted so that it will 
  828. work in protected mode.  In either case, the CPU signals a GP fault 
  829. when your program tries to violate protection.  This makes protected 
  830. mode a superb environment for software development:  the hardware 
  831. will help you find bugs and trouble spots.
  832.  
  833.    In the case of the buggy version of MEM, the message "General 
  834. protection fault detected" message alerts us to a bug that the CPU 
  835. found for us:  the program dereferences pointers without checking if 
  836. malloc() succeeded.  If you examine the register dump produced by 
  837. 286|DOS-Extender Lite, you will note that the ES register is set to 
  838. zero, suggesting we tried to dereference a NULL pointer.  This NULL 
  839. pointer checking is not inserted by the compiler:  the Intel 
  840. processor takes care of it in hardware, making it just one example of 
  841. the many checks that the CPU does in protected mode, with no extra 
  842. work on our part.
  843.  
  844. ----------------------------------------------------
  845. Debugging with TDW Under MS-DOS 
  846. (with the 286|DOS-Extender Software Development Kit)
  847. ----------------------------------------------------
  848.  
  849.    As explained at the beginning of this file, 286|DOS-Extender Lite 
  850. does not support debugging.  The 286|DOS-Extender SDK, however, 
  851. supports the powerful debugging features in the protected mode Windows
  852. version of Turbo Debugger (TDW) that comes with Borland C++.  We would
  853. like to take this opportunity to illustrate the debugging support 
  854. available with the 286|DOS-Extender SDK.  
  855.  
  856.    For an example, let's look at the buggy MEM program.  A protected 
  857. mode symbolic debugger like TDW would let us pinpoint the exact 
  858. location of the bug in the MEM program (if we didn't already know 
  859. it).  
  860.  
  861.    We wouldn't run TDW under Windows, though, or if we did, we'd be 
  862. running it in a DOS box.  We would use 286|DOS-Extender to run TDW 
  863. under MS-DOS, right from the DOS prompt, without Windows.
  864.  
  865.    Just as 286|DOS-Extender runs your protected mode applications 
  866. under MS-DOS, it can run a protected mode debugger like TDW.  
  867. (286|DOS-Extender makes this possible through its support for dynamic 
  868. link libraries (DLLs).  This feature is explained in the 
  869. documentation for the 286|DOS-Extender SDK.)  TDW runs under DOS 
  870. because 286|DOS-Extender supplies Windows-emulation libraries such as 
  871. KERNEL.DLL, USER.DLL, and WINDEBUG.DLL.
  872.  
  873.    But why would we use a Windows debugger to debug DOS programs? 
  874. Because TDW understands protected mode programs.  In fact, 286|DOS-
  875. Extender executables use the same standard Microsoft segmented-
  876. executable file format used by Windows.  This is why TLINK, which 
  877. knows how to produce Windows executables, can also produce 286|DOS-
  878. Extender executables.
  879.  
  880.    Why can't we just use the protected mode TD286 debugger?  Because 
  881. TD286 merely runs in protected mode:  it doesn't know how to debug 
  882. protected mode programs.  In a way, TD286 is a "cross-development 
  883. tool":  it's a protected mode debugger, used to debug real mode 
  884. programs.  When running under 286|DOS-Extender, TDW is a protected 
  885. mode DOS debugger, used to debug protected mode DOS programs.  
  886.  
  887.    To make symbolic information available for TDW under DOS, we would 
  888. use the Borland C++ -v switch:  
  889.  
  890. C:\>bcc286 -v buggymem.c
  891.  
  892.    If you happen to be developing 286|DOS-Extender applications with 
  893. Microsoft C, and want to debug with Borland's Turbo Debugger rather 
  894. than with  Microsoft's CodeView, you would compile with the Microsoft 
  895. -Zi (CodeView) switch, then run the Borland TDCONVRT utility to 
  896. prepare your program for TDW.  You must use the TDCONVRT -c 
  897. switch.  For example:
  898.  
  899. C:\>cl -Lp -AL -Zi buggymem.c
  900.  
  901. C:\>\borlandc\bin\tdconvrt -c buggymem
  902.  
  903.    To debug a protected mode program under DOS, run TDW, together 
  904. with your program, under 286|DOS-Extender:
  905.  
  906. C:\>RUN286 \borlandc\bin\tdw buggymem
  907.  
  908.    You would probably tire of typing this long command line each time 
  909. you want to debug a protected mode DOS program.  The Phar Lap BIND286 
  910. utility can be used to create a new executable, TDP.EXE, whose name 
  911. you would then type on the DOS command line instead of RUN286 TDW.  
  912. To build TDP.EXE:
  913.  
  914. C:\>bind286 \borlandc\bin\tdw -exe \RUN286\bin\tdp.exe
  915.  
  916.    Whether you run TDP or RUN286 TDW, you can do source-level 
  917. debugging of protected mode DOS programs without having to learn a 
  918. new debugger.  For the remainder of this discussion, we shall refer 
  919. to TDW running under 286|DOS-Extender as TDP.  If you do not already 
  920. know how to use Turbo Debugger, refer to the Borland documentation or 
  921. one of several third-party books, such as Tom Swan's Mastering Turbo 
  922. Debugger (Carmel IN:  Hayden Books, 1990, 618 pp., ISBN 0-672-48454-4).  
  923.  
  924.    TDP displays just a few differences from real mode TD.  The major 
  925. difference is that TDP can debug multimegabyte applications, whereas 
  926. real mode TD can't.  TDP can also be extended using Phar Lap's PMON, 
  927. which provides the ability to walk the protected mode descriptor 
  928. tables, display DPMI interrupt and exception vectors, and so on.
  929.  
  930.    Inside TDP, you can press F9 to run a program, F8 to step, F7 to 
  931. trace, F2 to set a breakpoint, CTRL-W to watch an expression, F1 to 
  932. get help, and so on.  Alternatively, you can use the pull-down menus 
  933. and the mouse.  TDP can be run in 25-line or 43/50-line mode.
  934.  
  935.    When debugging BUGGYMEM, if you press F9, malloc would eventually 
  936. run out of memory.  TDP would run into our offending code, and place 
  937. the cursor on the REP STOSW instruction and display this message:
  938.  
  939. Exception 13, error code 0
  940.  
  941.    Sure enough, forgetting to check the return value from malloc() 
  942. causes an "exception 13" (also known as an INT 0D, a General 
  943. protection violation, or a GP fault).  The CPU window would show
  944. that the ES segment register holds a value of zero, indicating that
  945. we're trying to do something with a NULL pointer.
  946.  
  947.    In real mode, the interpretation of 0:0 as a NULL pointer is an 
  948. arbitrary convention, because in real mode, 0:0 is a completely 
  949. legitimate address (it holds the address of the divide-by-zero 
  950. interrupt handler).  Protected mode, however, provides hardware 
  951. support for the notion of a NULL pointer.
  952.  
  953.    Where would we be?  By selecting the "Stack" option from the TDP 
  954. "View" menu, and then navigating the stack view window, we would see 
  955. that we're somewhere inside the call to memset() inside main().  This 
  956. is not surprising, given that the call to memset() immediately 
  957. follows the incorrect use of malloc().
  958.  
  959.    Can you imagine debugging this code without TDW?  We hope you will 
  960. see from this example how much easier protected mode programming can 
  961. be with the features available in the 286|DOS-Extender SDK.
  962.  
  963. --------------------------------
  964. What About Direct Screen Writes?
  965. --------------------------------
  966.  
  967.    So far we have seen that straightforward C or C++ code can be 
  968. taken and run, without source-code changes, under Phar Lap's 286|DOS-
  969. Extender Lite.  
  970.  
  971.    But while they allocated large amounts of memory, and showed some 
  972. of the benefits of 286|DOS-Extender Lite and the basic process of 
  973. developing applications with 286|DOS-Extender Lite, our MEMTEST 
  974. sample programs are too simple to illustrate all the issues involved 
  975. in PC software development.  The remainder of this chapter quickly 
  976. examines some of the issues pertinent to Borland C++.
  977.  
  978.    Clearly, MEMTEST is not a typical PC program.  For example, it 
  979. uses the portable printf() function to display output.  With the 
  980. exception of programs such as compilers and linkers, however, 
  981. applications for the PC tend to use direct screen writes or other 
  982. low-level code.  How well do such programs run under 286|DOS-Extender 
  983. Lite?
  984.  
  985.    We saw earlier that DOS (INT 21h) and BIOS calls are supported in 
  986. protected mode.  Thus, low-level PC code runs as is under 286|DOS-
  987. Extender Lite.
  988.  
  989.    However, the PC programming interface doesn't consist only of DOS 
  990. and BIOS calls.  The ability to peek and poke absolute memory 
  991. locations is also part of the PC programming interface, and this 
  992. ability normally assumes that the program is running in real mode.
  993.  
  994.    Direct screen writes are a good example, because these assume that 
  995. absolute memory locations such as B8000h can be addressed through 
  996. pointers such as B800:0000.  When a program is manipulating an 
  997. address such as B800:0000, it's really interested in absolute memory 
  998. location B8000h.  Similarly, when it manipulates an address such as 
  999. 0040:006C, it's really interested in absolute memory location 46Ch.  
  1000. In protected mode the equivalence of B8000h and B800:0000 no longer 
  1001. holds.  It is precisely because protected mode throws out this 
  1002. equivalence that it can provide more than one megabyte of memory.
  1003.  
  1004.    Besides the tiny video_mode() function we saw in the discussion of 
  1005. DOS and BIOS calls, a program that does direct screen writes probably 
  1006. would also include code such as the following, which puts the 
  1007. paragraph address of the text mode video display memory (0xB000 or 
  1008. 0xB800) into a global variable.  This code also uses the MK_FP() 
  1009. macro from DOS.H in Borland C++ to create a far pointer to B000:0000 
  1010. or to B800:0000:
  1011.  
  1012. unsigned short get_vid_mem(void)
  1013. {
  1014.     int vmode = video_mode();
  1015.     unsigned short seg;
  1016.  
  1017.     if (vmode == 7) /* monochrome */
  1018.     seg = 0xB000;
  1019.     else if ((vmode == 2) || (vmode == 3))
  1020.     seg = 0xB800;
  1021.     else
  1022.     return 0;
  1023.  
  1024.     return seg;
  1025. }
  1026.  
  1027. static BYTE far *vid_mem;   /* use far pointer */
  1028.  
  1029. video_init(void)
  1030. {
  1031.     vid_mem = MK_FP(get_vid_mem(), 0);
  1032. }
  1033.  
  1034. #define SCR(y,x)    (((y) * 160) + ((x) << 1))
  1035.  
  1036. void wrt_str(int y, int x, ATTRIB attr, unsigned char *p)
  1037. {
  1038.     BYTE far *v = vid_mem + SCR(y, x);
  1039.     while (*p)
  1040.     {
  1041.     *v++ = *p++;
  1042.     *v++ = attr;
  1043.     }
  1044. }
  1045.  
  1046.    But if we now try to run a program that includes this code under 
  1047. 286|DOS-Extender Lite, we get another one of those "General 
  1048. protection fault detected" messages, just as if our code contained a 
  1049. bug:
  1050.  
  1051. C:\>bcc286 memtest3.c
  1052.  
  1053. C:\>memtest3
  1054. Fatal error 286.3330:  General protection fault detected.
  1055. PID=0001  TID=0001  SID=0001  ERRORCODE=B800
  1056. AX=0041  BX=0098  CX=01ED  DX=0000  SI=042E  DI=042E  BP=0F08
  1057. CS:IP=022F:01FD   DS=024F  ES=024F  SS:SP=024F:0F06   FLAGS=3206
  1058.  
  1059.    Our code doesn't contain a bug.  However, ERRORCODE=B800 suggests 
  1060. that simply loading the paragraph address of the video display memory 
  1061. into a segment register such as DS or ES isn't going to work in 
  1062. protected mode.
  1063.  
  1064.    It's extremely simple to get this code working in protected mode.  
  1065. To write directly to video memory from protected mode, you need a 
  1066. function call that "maps" absolute memory locations into the address 
  1067. space of your protected mode program.  The only function that needs 
  1068. to be changed is get_vid_mem(), so that instead of returning 0xB000 
  1069. or 0xB800, it returns a protected mode selector that maps one of 
  1070. these real mode paragraph addresses.  To do this, we use the Phar Lap
  1071. API (PHAPI) function DosMapRealSeg(), whose prototype is in PHAPI.H.
  1072.  
  1073. #ifdef DOSX286
  1074. // symbol DOSX286 automatically defined by BCC286
  1075. #include <phapi.h>
  1076. #endif
  1077.  
  1078. unsigned short get_vid_mem(void)
  1079. {
  1080.     int vmode = video_mode();
  1081.     unsigned seg;
  1082.  
  1083.     if (vmode == 7)
  1084.     seg = 0xB000;
  1085.     else if ((vmode == 2) || (vmode == 3))
  1086.     seg = 0xB800;
  1087.     else
  1088.     return 0;
  1089.  
  1090.  
  1091. #ifdef DOSX286
  1092. {
  1093.     unsigned short sel;  
  1094.     /*
  1095.        DosMapRealSeg() takes a real mode paragraph address
  1096.        and a count of bytes, and gives back a selector that
  1097.        can be used to address the memory from protected 
  1098.        mode.  Like all PHAPI functions, DosMapRealSeg()
  1099.        returns 0 for success, or a non-zero error code.  Any 
  1100.        other information (such as the selector we're 
  1101.        interested in) is returned via parameters.
  1102.     */
  1103.     if (DosMapRealSeg(seg, (long) 25*80*2, &sel) == 0)
  1104.     return sel;
  1105.     else
  1106.     return 0;
  1107. }
  1108. #endif
  1109.  
  1110.     return seg;
  1111. }
  1112.  
  1113.    In the larger program from which this code was extracted, this was 
  1114. the only source-code change needed to get the program running under 
  1115. 286|DOS-Extender Lite.  All the actual direct screen writes ran in 
  1116. protected mode without modification.  Most graphics code can be 
  1117. ported to 286|DOS-Extender Lite in the same way, simply by changing 
  1118. the function that returns the segment number of video memory, to use 
  1119. DosMapRealSeg (0xA000, ...).  Since the PHAPI-specific code is inside 
  1120. an #ifdef, the same code can  be compiled for real mode with BCC, or 
  1121. compiled for protected mode by compiling with BCC286 (which 
  1122. automatically defines DOSX286).
  1123.  
  1124.    When the program is finished with the selector to video memory, it 
  1125. should free it by calling DosFreeSeg():
  1126.  
  1127. DosFreeSeg(FP_SEG(vid_mem));    // segment of far pointer
  1128.  
  1129.    That's all it takes to get direct screen writes working in 
  1130. protected mode.
  1131.  
  1132. -------
  1133. Summary
  1134. -------
  1135.  
  1136.    Any given program probably will require only a few PHAPI functions;
  1137. the vast majority of your DOS code will work "as is" under 286|DOS-
  1138. Extender Lite.  You can preserve your investment and your customer's 
  1139. investment in MS-DOS.
  1140.  
  1141.    286|DOS-Extender Lite turns Borland C++ into a toolkit for 
  1142. protected mode DOS development.  Just by using BCC286 rather than 
  1143. BCC, your Borland C++ programs break the 640K barrier.
  1144.  
  1145.  
  1146. --------------------------------------------
  1147. Chapter 2
  1148. Using 286|DOS-Extender Lite with Borland C++
  1149. --------------------------------------------
  1150.  
  1151.  
  1152.    The easiest way to compile and link 286|DOS-Extender Lite programs 
  1153. with Borland C++ is to use BCC286, available with 286|DOS-Extender Lite:
  1154.  
  1155. C:\TEST>bcc286 memtest.c
  1156.  
  1157. C:\TEST>memtest
  1158.  
  1159.    C++ programs can also be compiled and linked for 286|DOS-Extender 
  1160. Lite:
  1161.  
  1162. C:\TEST>bcc286 memtest.cpp
  1163.  
  1164. C:\TEST>memtest
  1165.  
  1166.    BCC286.EXE will usually be installed in C:\LITE286\BIN, which must 
  1167. be on your path.  BCC286 uses Borland's BCC.EXE and TLINK.EXE; these 
  1168. must also be on the path.  For example:
  1169.  
  1170. C:\TEST>set path=c:\LITE286\bin;c:\borlandc\bin;c:\bin
  1171.  
  1172.    286|DOS-Extender Lite requires TLINK version 4.0 or higher, 
  1173. shipped with Borland C++; it will not work with the earlier Turbo C 
  1174. or Turbo C++ versions of TLINK.  286|DOS-Extender Lite also requires 
  1175. the Borland C++ command-line tools, and will not work with the BC 
  1176. integrated development environment (IDE).
  1177.  
  1178.    BCC286 also uses C0PL.OBJ and PHAPI.LIB, which come with 286|DOS-
  1179. Extender Lite, and BCL286.LIB, which is built when you install 
  1180. 286|DOS-Extender Lite.  These files must be located on the path, or 
  1181. in a directory named in an optional LIB environment variable, or in 
  1182. the library path specified with a BCC286 -L command-line parameter.  
  1183. These files are usually installed in C:\LITE286\BC3\LIB.  If you 
  1184. receive a message from BCC286 such as "Cannot find C0PL.OBJ", you  
  1185. need to specify a library search path.  For example:
  1186.  
  1187. C:\TEST>bcc286 -L\LITE286\bc3\lib;\borlandc\lib phoo.c
  1188.  
  1189. or:
  1190.  
  1191. C:\TEST>set lib=\LITE286\bc3\lib;\borlandc\lib
  1192.  
  1193. C:\TEST>bcc286 phoo.c
  1194.  
  1195.    A good place to put switches such as -L and -I (include file path) 
  1196. is inside the Borland C++ TURBOC.CFG file.  For example:
  1197.  
  1198. C:\TEST>type turboc.cfg
  1199. -L\LITE286\bc3\lib;\borlandc\lib;\borlandc\classlib\lib
  1200. -I\borlandc\include;\LITE286\inv
  1201. -G
  1202. -O
  1203.  
  1204.    BCC286 does a large model compile with BCC and then creates a 
  1205. module-definition (.DEF) file which is passed to TLINK, along with 
  1206. protected mode object modules and libraries, to create a protected 
  1207. mode executable which can be run from the DOS command line.  BCC286 
  1208. places a loader inside each protected mode executable; this loader 
  1209. automatically runs 286|DOS-Extender Lite (LITE286.EXE) each time you 
  1210. start the protected mode executable from the DOS command line.
  1211.  
  1212. ----------------------
  1213. BCC286 Usage in Detail
  1214. ----------------------
  1215.  
  1216.    If you run BCC286 without any command-line arguments, it displays 
  1217. the standard BCC options followed by the additional options supplied 
  1218. by BCC286:
  1219.  
  1220. BCC286  Version 2.1 Copyright (c) 1991 Phar Lap Software, Inc.
  1221. Borland C++  Version 3.1 Copyright (c) 1991 Borland International
  1222. Syntax is: BCC [ options ] file[s]     * = default; -x- = turn switch x off
  1223.   -1      80186/286 Instructions    -2      80286 Protected Mode Inst.
  1224.   -Ax     Disable extensions        -B      Compile via assembly
  1225.   -C      Allow nested comments     -Dxxx   Define macro
  1226.   -Exxx   Alternate Assembler name  -G      Generate for speed
  1227.   -Hxxx   Use pre-compiled headers  -Ixxx   Include files directory
  1228.   -K      Default char is unsigned  -Lxxx   Libraries directory
  1229.   -M      Generate link map         -N      Check stack overflow
  1230.   -Ox     Optimizations             -P      Force C++ compile
  1231.   -Qxxx   Memory usage control      -S      Produce assembly output
  1232.   -Txxx   Set assembler option      -Uxxx   Undefine macro
  1233.   -Vx     Virtual table control     -Wxxx   Create Windows application
  1234.   -X      Suppress autodep. output  -Yx     Overlay control
  1235.   -Z      Suppress register reloads -a      Generate word alignment
  1236.   -b    * Treat enums as integers   -c      Compile only
  1237.   -d      Merge duplicate strings   -exxx   Executable file name
  1238.   -fxx    Floating point options    -gN     Stop after N warnings
  1239.   -iN     Max. identifier length    -jN     Stop after N errors
  1240.   -k      Standard stack frame      -lx     Set linker option
  1241.   -mx     Set Memory Model          -nxxx   Output file directory
  1242.   -oxxx   Object file name          -p      Pascal calls
  1243.   -r    * Register variables        -u    * Underscores on externs
  1244.   -v      Source level debugging    -wxxx   Warning control
  1245.   -y      Produce line number info  -zxxx   Set segment names
  1246.  
  1247. BCC286:  Phar Lap 286|DOS-Extender driver for Borland C++
  1248.          produces protected-mode DOS executables
  1249. usage:   bcc286 [options] [filenames]
  1250. options: any bcc option or:
  1251.   -stack=n    set stack size
  1252.   -nostub     for smaller file without stub loader
  1253.   -keep       keep BCC286's RSP, LNK, and DEF files
  1254.  
  1255.  
  1256. BCC286 Input Files
  1257. ------------------
  1258.  
  1259.    BCC286 accepts the following file types:
  1260.  
  1261.  C source files (default extension .C)
  1262.  C++ source files (default extension .CPP)
  1263.  Assembly-language source files (default extension .ASM)
  1264.  .OBJ object modules
  1265.  .LIB object libraries
  1266.  .DEF module-definition files
  1267.  
  1268.    Pathnames can be specified using either backslashes or forward 
  1269. slashes:
  1270.  
  1271. C:\TEST>bcc286 \phoo\bar\hello.cpp
  1272.  
  1273. C:\TEST>bcc286 /phoo/bar/hello.cpp
  1274.  
  1275.    In addition to standard BCC operation (described in the Borland C++ 
  1276. User's Guide) BCC286 handles .DEF and .ASM files in the following way:
  1277.  
  1278.  .DEF files are passed to TLINK, and override the standard BCC286 
  1279.    module-definition file.  For example:
  1280.  
  1281.    C:\TEST>bcc286 hello.c hello.def
  1282.  
  1283.  If an .ASM file is the first file passed to BCC286, then no 
  1284.   startup code is linked in.  For example:
  1285.  
  1286.   C:\TEST>bcc286 hello.asm phoo.c bar.c
  1287.  
  1288.    Like BCC, BCC286 also accepts response files and configuration 
  1289. files, including TURBOC.CFG.  For example:
  1290.  
  1291. C:\TEST>type hello.rsp
  1292. -v
  1293. -DDEBUGGING
  1294. -L\LITE286\bc3\lib;\borlandc\lib
  1295. hello.c
  1296.  
  1297. C:\TEST>bcc286 @hello.rsp
  1298.  
  1299. C:\TEST>type hello.cfg
  1300. -v -DDEBUGGING -L\LITE286\bc3\lib;\borlandc\lib
  1301.  
  1302. C:\TEST>bcc286 +hello.cfg hello.c
  1303.  
  1304.    Response and configuration files do not suffer from the 128-byte 
  1305. limitation of the DOS command line.
  1306.  
  1307.    BCC286-specific switches such as -stack should not be placed in 
  1308. configuration files.  They can, however, be placed in response files.
  1309.  
  1310.  
  1311. Environment Variables
  1312. ---------------------
  1313.  
  1314.    BCC286 switches can also be placed in an optional BCC286 
  1315. environment variable.  Except for BCC286-specific switches such as 
  1316. -stack or -nostub, switches placed in the BCC286 environment variable 
  1317. will also be passed on to BCC.  For example:
  1318.  
  1319. C:\TEST>set bcc286=-v -DDEBUGGING -L\LITE286\bc3\lib;\borlandc\lib
  1320.  
  1321. C:\TEST>bcc286 phoo.c bar.c
  1322.  
  1323.    As noted earlier, in addition to the BCC -L switch for specifying 
  1324. a library search path, BCC286 will also use an optional LIB 
  1325. environment variable.  For example:
  1326.  
  1327. C:\TEST>set lib=\borlandc\lib;\LITE286\bc3\lib
  1328.  
  1329. C:\TEST>bcc286 phoo.c bar.c phoobar.lib
  1330.  
  1331. ---------------
  1332. BCC286 Switches
  1333. ---------------
  1334.  
  1335.    BCC286 provides a number of features not found in BCC, including 
  1336. the ability to specify .DEF files on the command line and to set the 
  1337. stack size.  
  1338.  
  1339.    Most BCC286 switches, whether specified on the command line, in 
  1340. the BCC286 environment variable, or in a response or configuration 
  1341. file, are passed down to BCC.  The following switches are not passed 
  1342. down, and are unique to BCC286:
  1343.  
  1344.  
  1345. -keep
  1346. -----
  1347.  
  1348.    Normally, BCC286 removes the three temporary files it creates:  
  1349. the BCC response file, TMP.RSP; the TLINK response file, TMP.LNK; and 
  1350. the module-definition file, TMP.DEF.  If you use the -keep switch, 
  1351. BCC286 won't remove these files; you'll be able to examine, copy, or 
  1352. edit them for your own use with BCC and TLINK.
  1353.  
  1354.  
  1355. -nostub
  1356. -------
  1357.  
  1358.    286|DOS-Extender Lite programs produced with BCC286 can be run 
  1359. directly from the DOS command line because they include a "real mode 
  1360. stub" called GORUN286.EXE, which reinvokes the program under 
  1361. LITE286.EXE.  This GORUN286 stub increases the size of the program by 
  1362. about 10 KB.  The BCC286 -nostub switch suppresses the use of this 
  1363. stub, resulting in smaller executable files which, however, can only 
  1364. be run from the DOS command line by explicitly using LITE286; 
  1365. otherwise they produce a confusing message and exit back to DOS.  For 
  1366. example:
  1367.  
  1368. C:\TEST>bcc286 hello.c
  1369.  
  1370. C:\TEST>hello
  1371. hello world!
  1372.  
  1373. C:\TEST>bcc286 -nostub hello.c
  1374.  
  1375. C:\TEST>hello
  1376. This program must be run under OS/2.
  1377.  
  1378. C:\TEST>LITE286 hello
  1379. hello world!
  1380.  
  1381.    Note, however, that under the full-fledged 286|DOS-Extender,the 
  1382. DosExecPgm() function and the spawn() family of functions in the C 
  1383. run-time library can directly invoke protected mode programs without 
  1384. a real mode stub.  
  1385.  
  1386.    If you want to specify a real mode stub other than GORUN286, use a 
  1387. .DEF file.  As noted earlier, .DEF files can be specified on the 
  1388. BCC286 command line.  For example:
  1389.  
  1390. C:\TEST>type hello.def
  1391. PROTMODE
  1392. STUB 'mystub.exe'
  1393. EXPORTS BCC286_EXE
  1394.  
  1395. C:\TEST>bcc286 hello.c hello.def
  1396.  
  1397.  
  1398. -stack=xxx
  1399. ----------
  1400.  
  1401.    This switch can be used to set the stack size of a program.  For 
  1402. example:
  1403.  
  1404. C:\TEST>bcc286 -stack=10240 hello.c
  1405.  
  1406.    Stack size can alternatively be specified inside a .DEF file.  For 
  1407. example:
  1408.  
  1409. C:\TEST>type hello.def
  1410. PROTMODE
  1411. STUB 'gorun286.exe'
  1412. STACKSIZE 10240
  1413. EXPORTS BCC286_EXE
  1414.  
  1415. C:\TEST>bcc286 hello.c hello.def
  1416.  
  1417.    The default stack size defined by BCC286 is 4 KB.  If you receive 
  1418. a TLINK "Group DGROUP exceeds 64K" error message, you can try reducing 
  1419. the stack size.
  1420.  
  1421.  
  1422. ---------------------------
  1423. BCC286 Differences from BCC
  1424. ---------------------------
  1425.  
  1426.    BCC286 has the following differences from BCC:
  1427.  
  1428.  The only supported memory model switch is -ml (large model).  If 
  1429.   you need near or huge data, use the near, far, and huge keywords in 
  1430.   your source code to create "mixed model" programs.
  1431.  
  1432.  Because 286|DOS-Extender Lite, like Windows, does not support 
  1433.   overlays, the BCC -Yo and TLINK -o overlay switches cannot be used 
  1434.   when creating 286|DOS-Extender Lite programs.  286|DOS-Extender 
  1435.   Lite does not suffer from the 640K limitations of MS-DOS, so 
  1436.   overlays are usually unnecessary.
  1437.  
  1438. -------------------
  1439. Using BCC and TLINK
  1440. -------------------
  1441.  
  1442.    If you would prefer to use BCC and TLINK directly to compile and 
  1443. link 286|DOS-Extender Lite programs, instead of using BCC286, there 
  1444. are certain command-line options, object modules, libraries, and 
  1445. module-definition files which you must use.  These are normally taken 
  1446. care of automatically by BCC286.
  1447.  
  1448.    For example, to produce a protected mode DOS version of HELLO.EXE, 
  1449. without BCC286:
  1450.  
  1451. C:\TEST>bcc -c -ml -2 -DDOSX286 -h hello.c
  1452.  
  1453. C:\TEST>type protmode.def
  1454. PROTMODE
  1455. STUB      'gorun286.exe'
  1456. EXPORTS   BCC286_EXE 
  1457.  
  1458. C:\TEST>type hello.lnk
  1459. \LITE286\BC3\lib\c0pl hello
  1460. hello
  1461. nul
  1462. phapi bcl286
  1463. protmode
  1464.  
  1465. C:\TEST>tlink /L\LITE286\BC3\lib @hello.lnk
  1466.  
  1467.    The following briefly describes each switch, statement, or file.  
  1468. This description is necessary only if you are compiling and linking 
  1469. directly with BCC and TLINK, rather than using BCC286.
  1470.  
  1471.  
  1472. BCC Switches
  1473. ------------
  1474.  
  1475.  -c (compile only):  A module-definition (.DEF) file must be 
  1476.   specified when using Borland TLINK to produce 286|DOS-Extender Lite 
  1477.   programs, but BCC (unlike BCC286) does not accept .DEF files on its 
  1478.   command line.  Therefore, TLINK must be run as a separate step.
  1479.  
  1480.  -ml (large model):  Large model is required when using Borland C++ 
  1481.   to produce 286|DOS-Extender Lite programs.  The near, far, and huge 
  1482.   keywords can be used in source code to produce a "mixed model" 
  1483.   program.
  1484.  
  1485.  -2 (80286 protected mode instructions):  This switch is usually 
  1486.   not necessary, but BCC produces better code when it is used.  Since 
  1487.   286|DOS-Extender Lite programs run only on 80286 and higher 
  1488.   machines, it makes sense to use this switch.  If a user attempts to 
  1489.   run a 286|DOS-Extender Lite program on an 8086 or 8088 machine, 
  1490.   LITE286 detects the error before your program starts.  
  1491.  
  1492.   The -2 switch is necessary if your C or C++ program includes inline 
  1493.   assembly-language statements that use 286-based protected mode 
  1494.   instructions such as LAR or LSL.
  1495.  
  1496.  -DDOSX286 (define the symbol DOSX286):  This symbol is not 
  1497.   strictly necessary, but BCC286 automatically defines it, and some 
  1498.   of the examples in this manual assume that it has been defined.
  1499.  
  1500.  
  1501. .DEF File Statements
  1502. --------------------
  1503.  
  1504.    A .DEF file provides information to the linker about the contents 
  1505. and system requirements of a protected mode program, including 
  1506. Windows and 286|DOS-Extender Lite programs.  A .DEF file is needed to 
  1507. produce a 286|DOS-Extender Lite program with Borland C++.  BCC286 
  1508. automatically produces a standard .DEF file that contains the 
  1509. following statements (the line that begins with a semicolon is a 
  1510. comment):
  1511.  
  1512. ; protmode.def
  1513. PROTMODE
  1514. STUB 'gorun286.exe'
  1515. EXPORTS BCC286_EXE
  1516.  
  1517.    If you are running BCC and TLINK directly without using BCC286, 
  1518. then you must specify your own .DEF file.  You can create one 
  1519. standard PROTMODE.DEF for use with all your programs, or create a 
  1520. separate customized .DEF file for each program.
  1521.  
  1522.    The statements used in the default .DEF file created by BCC286 are 
  1523. explained below:
  1524.  
  1525.  PROTMODE:  The PROTMODE statement should almost always be used.  
  1526.   Only omit this statement when you are creating a real mode DLL.
  1527.  
  1528.  STUB 'gorun286.exe':  The STUB statement embeds the specified real 
  1529.   mode DOS executable at the beginning of the protected mode 
  1530.   executable.  This real mode DOS executable then becomes the "stub" 
  1531.   which is run whenever the program is invoked from the DOS command 
  1532.   line.
  1533.  
  1534.   GORUN286.EXE is a real mode program which reinvokes 286|DOS-
  1535.   Extender Lite programs under LITE286.EXE, creating the useful 
  1536.   illusion that MS-DOS is capable of running protected mode programs.  
  1537.   If a different real mode stub is specified, the 286|DOS-Extender 
  1538.   Lite program may have to be run from the DOS command line with an 
  1539.   explicit LITE286 statement.
  1540.  
  1541.   If the STUB statement is omitted and the 286|DOS-Extender Lite 
  1542.   program is run directly from the DOS command line, it will print 
  1543.   out the confusing and untrue statement "This program must be run 
  1544.   under OS/2."
  1545.  
  1546.  EXPORTS BCC286_EXE:  Currently, this is required only for Borland 
  1547.   C++ executables that use floating-point math.  However, it is 
  1548.   safest  to include this statement in all Borland C++ executables.
  1549.  
  1550.  
  1551. TLINK Switches and Files
  1552. ------------------------
  1553.  
  1554.  /L\lite286\bc3\lib:  The TLINK /L switch specifies a library 
  1555.   search path.  The libraries PHAPI.LIB and BCL286.LIB, and the 
  1556.   C0PL.OBJ startup object module, are usually located in 
  1557.   C:\LITE286\BC3\LIB.
  1558.  
  1559.  @hello.lnk:  While TLINK can be run with all necessary files and 
  1560.   switches named right on the command line, in most genuine programs 
  1561.   this will run up against the 128-byte DOS command line limit.  For 
  1562.   example, even protected mode HELLO requires a long command line if 
  1563.   you're not using BCC286:
  1564.  
  1565.   C:\TEST>tlink /L\LITE286\bc3\lib c0pl hello,hello,,bcl286 phapi,protmode
  1566.  
  1567.       The alternative is to put TLINK input in a response file.  
  1568.   Newlines are used to delimit fields, and a + sign is used to 
  1569.   continue fields across multiple lines.  The TLINK fields are 
  1570.   obj,exe,map,lib,def.  For example:
  1571.  
  1572.   C:\TEST>type hello.lnk
  1573.   c0pl +
  1574.   hello
  1575.   hello
  1576.   nul
  1577.   bcl286 phapi
  1578.   protmode
  1579.  
  1580.   C:\TEST>tlink /L\LITE286\bc3\lib @hello.lnk
  1581.  
  1582.  C0PL.OBJ:  This is 286|DOS-Extender Lite protected mode large 
  1583.   model startup code for Borland C++.  This file is shipped with 
  1584.   286|DOS-Extender Lite SDK and will generally be located in 
  1585.   C:\LITE286\BC3\LIB.
  1586.  
  1587.  PHAPI.LIB:  This library contains import references for Phar Lap 
  1588.   application program interface (PHAPI) functions exported from the 
  1589.   286|DOS-Extender Lite DLLs.
  1590.  
  1591.  BCL286.LIB:  This library contains a protected mode compatible 
  1592.   version of the Borland C++ run-time library.  This file is built 
  1593.   during installation of 286|DOS-Extender Lite, from Borland's 
  1594.   CL.LIB, and will generally be located in C:\LITE286\BC3\LIB.
  1595.  
  1596. --------------------------------
  1597. Building Floating-Point Programs
  1598. --------------------------------
  1599.  
  1600.    By default, BCC286 compiles program with the -f flag, for 
  1601. floating-point emulation.  If a program does not in fact require 
  1602. floating-point math, this makes the executable about 16 KB larger 
  1603. than necessary.  To generate smaller executables, use the BCC286 -f- 
  1604. (no floating point) option.  For example:
  1605.  
  1606. C:\TEST>bcc286 -f- hello.c
  1607.  
  1608. If you are using floating-point math, there are several issues which 
  1609. may be important:
  1610.  
  1611.  If you will be running floating-point protected mode applications 
  1612.   under Windows Enhanced mode, you must install the virtual device 
  1613.   driver PHARLAP.386, included with 286|DOS-Extender Lite.  Insert 
  1614.   the statement "DEVICE=C:\LITE286\BIN\PHARLAP.386" (or whatever path  
  1615.   is appropriate) in the [386Enh] section of the SYSTEM.INI file.
  1616.  
  1617.  BCC286 generates a protected-mode floating-point program when the 
  1618.   -f (floating point emulation), -ff (fast emulation), -f87 (8087 
  1619.   hardware) or -f287 (80287 hardware) option is used.  When linking 
  1620.   such programs directly with TLINK, however, you must specify the 
  1621.   correct library modules.  For example, if sqrt.exe uses floating-
  1622.   point emulation:
  1623.  
  1624.   C:\TEST>bcc286 -f sqrt.c
  1625.  
  1626.   or:
  1627.  
  1628.   C:\TEST>bcc -c -f -ml -2 -h -DDOSX286 sqrt.c
  1629.  
  1630.   C:\TEST>tlink c0pl sqrt emu286.lib,sqrt,,emu mathl phapi bcl286,protmode
  1631.  
  1632.   If sqrt2.exe uses 80287 floating-point hardware instructions:
  1633.  
  1634.   C:\TEST>bcc286 -f287 sqrt2.c
  1635.  
  1636.   or:
  1637.  
  1638.   C:\TEST>bcc -c -f287 -ml -2 -h -DDOSX286 sqrt2.c
  1639.  
  1640.   C:\TEST>tlink c0pl sqrt fp286.lib,sqrt2,,fp87 mathl phapi bcl286,protmode
  1641.  
  1642.    Note that floating-point emulation requires EMU286.LIB (linked in 
  1643. as an object module) and EMU.LIB, while programs that use floating-
  1644. point hardware instructions require FP286.LIB (linked in as an object 
  1645. module) and FP87.LIB.
  1646.  
  1647.  If you build floating-point applications without BCC286, you must 
  1648.   export the symbol BCC286_EXE.  Simply insert the statement "EXPORTS 
  1649.   BCC286_EXE" in your module-definition (.DEF) file.  For example:
  1650.  
  1651.   C:\TEST>type protmode.def
  1652.   PROTMODE
  1653.   EXPORTS   BCC286_EXE
  1654.  
  1655.  If you have a floating point coprocessor, but need to test 
  1656.   floating-point emulation, set 87=NO in the DOS environment.
  1657.  
  1658. ------------------------------------------------
  1659. Chapter 3
  1660. Running Protected Mode Applications Under MS-DOS
  1661. ------------------------------------------------
  1662.  
  1663.  
  1664.    So far we have seen that a program produced by BCC286 can be run 
  1665. directly from the DOS command line simply by typing its name, like 
  1666. any other DOS program.  286|DOS-Extender Lite programs can also be 
  1667. run under DOS without a command line, using any of the many 
  1668. alternatives to COMMAND.COM such as the DOSSHELL in DOS 5.
  1669.  
  1670.    By default, a protected mode program produced by BCC286 includes a 
  1671. real mode "stub" program called GORUN286.  When one of these programs 
  1672. is started under DOS, it is actually an embedded copy of GORUN286.EXE 
  1673. which runs initially.  GORUN286 is called a stub because its sole job 
  1674. is to restart the program under 286|DOS-Extender Lite, (LITE286.EXE).  
  1675. In other words, if PHOO.C is compiled with:
  1676.  
  1677. C:\TEST>bcc286 phoo.c
  1678.  
  1679. then running the program by typing its name:
  1680.  
  1681. C:\TEST>phoo
  1682.  
  1683. is equivalent to typing LITE286 followed by the name of the program:
  1684.  
  1685. C:\TEST>LITE286 phoo
  1686.  
  1687.    This seems like no big deal:  after all, we've saved only six 
  1688. letters and a space.  However, by eliminating the need to type those 
  1689. seven keystrokes, we have effectively hidden the DOS extender, and 
  1690. created the useful illusion that MS-DOS is an operating system that 
  1691. runs protected mode executables.
  1692.  
  1693.    Though usually hidden, the key components of 286|DOS-Extender Lite 
  1694. are LITE286.EXE, which loads 16-bit protected mode .EXE files under 
  1695. MS-DOS, and DOSCALLS.DLL, a dynamic link library (DLL) which contains 
  1696. some of the functions used by the protected mode Borland C++ startup 
  1697. code and run-time library.  The directory containing these files, for 
  1698. example C:\LITE286\BIN, must be located somewhere on the DOS file-
  1699. search path when you start an executable produced by BCC286.
  1700.  
  1701.    LITE286.EXE puts the computer into protected mode and loads your 
  1702. protected mode program.  Whenever your program makes DOS (INT 21h) or 
  1703. BIOS requests from protected mode, the DOS extender quickly and 
  1704. invisibly does the work of sending the requests off to MS-DOS or the 
  1705. ROM BIOS, which are running in real mode.  Thus, 286|DOS-Extender 
  1706. Lite is 100% compatible with DOS:  it's not an emulation, but 
  1707. literally an extension of DOS.
  1708.  
  1709. -------------
  1710. Compatibility
  1711. -------------
  1712.  
  1713.    There is another side to extending MS-DOS.  One of the key 
  1714. services of 286|DOS-Extender Lite, in contrast to any "roll your own" 
  1715. approach to protected mode, is compatibility.
  1716.  
  1717.    We've been assuming that the computer is in real mode, that 
  1718. LITE286 switches it into protected mode, installs some interrupt 
  1719. handlers, spawns your protected mode program and, when your program 
  1720. completes, puts the computer back into real mode.  
  1721.  
  1722.    But that would involve a simplistic view of the PC world in the 
  1723. 1990s.  Most users of 80386 and 80486 machines are employing memory 
  1724. managers such as EMM386, 386MAX and QEMM, or multitasking window 
  1725. systems such as DESQview or Microsoft Windows 3.x.  When such 
  1726. programs are running, the computer is not in real mode; it's running 
  1727. in a one-megabyte protected mode called virtual 8086 mode.  The 
  1728. assumption that a DOS extender can simply switch the machine from 
  1729. real mode to protected mode does not take into account the fact that 
  1730. many machines won't be in real mode.  Furthermore, users may be 
  1731. running programs such as VDISK or HIMEM or SMARTDrive, which use 
  1732. extended memory.  LITE286 must be able to run your protected mode 
  1733. program under DOS, yet be highly compatible with any other memory-
  1734. management software a user might be running.  
  1735.  
  1736.    One of the key questions about any protected mode MS-DOS solution 
  1737. is how compatible it is with all this different software.  Is it 
  1738. compatible with EMM386, 386MAX, and QEMM?  Does it run in a window 
  1739. inside DESQview/386 or Microsoft Windows 3.x Enhanced mode?  What if 
  1740. the machine is already running an expanded memory (EMS) or extended 
  1741. memory (XMS) manager?  What if there are VDISKs or a SMARTDrive?  What 
  1742. if your protected mode program has been spawned from within a 
  1743. 386|DOS-Extender program such as IBM Interleaf Publisher, 
  1744. Mathematica, or AutoCAD/386?
  1745.  
  1746.    286|DOS-Extender Lite handles all these situations gracefully.  It 
  1747. is compatible with all the PC industry standards for protected mode 
  1748. and extended memory.  In particular, it supports the Virtual Control 
  1749. Program Interface (VCPI) and DOS Protected Mode Interface (DPMI).  
  1750. VCPI is a specification developed jointly by Quarterdeck Office 
  1751. Systems and Phar Lap Software that allows EMS emulators and DOS 
  1752. extenders to coexist; it is an extension to EMS 4.0.  DPMI is a 
  1753. specification whose primary goal is compatibility between DOS 
  1754. extenders and DOS multitasking environments; DPMI was jointly 
  1755. developed by a committee including Microsoft, Intel, IBM, Phar Lap, 
  1756. Quarterdeck, Borland, Lotus, and other companies.  For more details 
  1757. on VCPI and DPMI, plus the old INT 15h and XMS standards, we 
  1758. recommend the book Extending DOS, Second Edition, edited by Ray Duncan
  1759. (Reading MA:  Addison-Wesley, 1991, 538 pp., ISBN 0-201-56798-9).
  1760.  
  1761.    To summarize, programs developed with 286|DOS-Extender Lite 
  1762. can run in a wide variety of environments.  LITE286 takes care of all 
  1763. the messy details of compatibility.  There is no separate 
  1764. configuration or "tune" program to run.
  1765.  
  1766. --------------------
  1767. LITE286 Requirements
  1768. --------------------
  1769.  
  1770.    LITE286 does have a few requirements, however:
  1771.  
  1772.  If an expanded memory (EMS) handler is installed, it must follow 
  1773.   the EMS 4.0 and VCPI specifications.  Almost all EMS managers 
  1774.   shipping today are VCPI-compatible; if yours isn't, contact the 
  1775.   manufacturer about upgrading to a new version.  (The exception is 
  1776.   IBM PC-DOS 4.01, which has an EMS manager that is not VCPI-
  1777.   compatible.)
  1778.  
  1779.  Microsoft's EMM386, included with DOS 5.0 and Windows 3.x, is 
  1780.   VCPI-compatible, and can therefore be used with 286|DOS-Extender 
  1781.   Lite.  However, the EMM386 NOEMS switch effectively disables VCPI 
  1782.   support, and therefore cannot be used.
  1783.  
  1784.  If an extended memory (XMS) manager such as HIMEM.SYS is 
  1785.   installed, we recommend setting a fairly large handle count.  For 
  1786.   example: 
  1787.  
  1788.   DEVICE=C:\WIN30\HIMEM.SYS /NUMHANDLES=127
  1789.  
  1790.  LITE286 will not run in the DOS compatibility box of OS/2 1.x, 
  1791.   because that environment is limited to a maximum of 640K.  However, 
  1792.   it will run in the DOS compatibility boxes of OS/2 2.0, which 
  1793.   provide DPMI support.
  1794.  
  1795.    One important word of warning:  Even though you don't have to 
  1796. explicitly type "LITE286" to run an executable produced by BCC286 
  1797. under MS-DOS, the LITE286.EXE file is necessary.  The directory 
  1798. containing both this file and DOSCALLS.DLL (for example 
  1799. C:\LITE286\BIN) must be located somewhere on the DOS file-search 
  1800. path.  If GORUN286 cannot find LITE286.EXE, it will display the 
  1801. message:
  1802.  
  1803. This program requires Phar Lap's 286|DOS-Extender
  1804.  
  1805.    If LITE286.EXE cannot find DOSCALLS.DLL (which should be located 
  1806. in the same directory as LITE286.EXE), it will display the message:
  1807.  
  1808. Fatal error 286.2190: Load program failed -- File not found -- DOSCALLS.DLL.
  1809.  
  1810.    If you receive either of these messages when trying to run an 
  1811. executable produced by BCC286, ensure that your path is correct.  For 
  1812. example:
  1813.  
  1814. C:\TEST>set path=c:\bin;c:\borlandc\bin;c:\LITE286\bin;c:\dos
  1815.  
  1816.    Note that neither LITE286.EXE nor the 286|DOS-Extender Lite DLLs 
  1817. can be shipped to end-users.  In order to prepare programs for 
  1818. redistribution, you must purchase the 286|DOS-Extender Run Time Kit 
  1819. (RTK), which lets you bind 286|DOS-Extender plus any necessary DLLs 
  1820. into your application (an application may consist of multiple 
  1821. executable files, all of which are covered by a single license 
  1822. agreement).
  1823.  
  1824.    With these details out of the way, protected mode programs will 
  1825. run under MS-DOS.
  1826.  
  1827. --------------
  1828. Error Messages
  1829. --------------
  1830.  
  1831.    The most common fatal error messages are described briefly in the 
  1832. following sample sessions.
  1833.  
  1834. C:\TEST>LITE286 phoobar
  1835. Fatal error 286.2190:  Load program failed -- File not found -- phoobar.exe.
  1836.  
  1837.    There is no program named PHOOBAR.EXE.  Either you have misspelled 
  1838. the program's name, or it is not located on the path.
  1839.  
  1840.  
  1841. C:\DOS>LITE286 bad
  1842. Fatal error 286.3330:  General protection fault detected.
  1843. PID=0001  TID=0001  SID=0001  ERRORCODE=0000
  1844. AX=0004  BX=0000  CX=0019  DX=008B  SI=00DA  DI=00DA  BP=0BE2
  1845. CS:IP=0237:001D   DS=024F  ES=0000  SS:SP=024F:0BDE   FLAGS=3246
  1846.  
  1847.    Your program violated a rule of protected mode, causing a General 
  1848. protection fault (GP fault).  There is a bug in your program, or a 
  1849. piece of code which must be modified before it can be run in 
  1850. protected mode, or you have unintentionally included real mode code 
  1851. (for example, real mode libraries) in the program.
  1852.  
  1853.  
  1854. C:\DOS>LITE286 mem
  1855. Fatal error 286.1000:  System does not have an 80286 (or newer) processor.
  1856.  
  1857.    You have attempted to run a 286|DOS-Extender Lite program on a 
  1858. machine which does not have an 80286, 80386, or 80486 processor.
  1859.  
  1860.  
  1861. C:\DOS>LITE286 mem
  1862. Fatal error 286.1020:  This program requires VCPI or DPMI in V86 mode.
  1863.  
  1864.    A program, probably an expanded-memory manager, has put the 
  1865. computer into virtual 8086 mode, but the program does not support 
  1866. either the Virtual Control Program Interface (VCPI) or the DOS 
  1867. Protected Mode Interface (DPMI).  Contact the manufacturer about 
  1868. upgrading to a later version which does support VCPI or DPMI, or 
  1869. remove the program.  Some of the expanded memory simulators with 
  1870. which LITE286 works are:
  1871.  
  1872.  QEMM 4.1 or later (Quarterdeck)
  1873.  386MAX 4.02 or later (Qualitas)
  1874.  CEMM 4.02 or later (COMPAQ)
  1875.  EMM386 (DOS 5.0, Microsoft Windows 3.x versions)
  1876.  
  1877. ----------------------------
  1878. LITE286 Command Line Options
  1879. ----------------------------
  1880.  
  1881.    What if you want to run your 286|DOS-Extender Lite program on 
  1882. hardware that is not 100% IBM-compatible?  What if you need to reserve 
  1883. a certain amount of extended memory because some other program 
  1884. doesn't adhere to any of the PC industry's standards for extended 
  1885. memory usage?  What if your program does a large amount of file I/O 
  1886. and you want LITE286 to use a larger conventional-memory "transfer 
  1887. buffer" for DOS and BIOS calls?
  1888.  
  1889.    LITE286 has a number of command line options which can be used in 
  1890. (frankly, rather rare) situations such as these.  If you type 
  1891. LITE286 -help on the DOS command line, a list of these command line 
  1892. options is displayed (the following display is not complete):
  1893.  
  1894. C:\DOS>LITE286 -help
  1895. 286|DOS-Extender Lite: 2.5 -- Copyright (C) 1986-92 Phar Lap Software, Inc.
  1896.       LITE286  switch(es) filename
  1897.  
  1898.      -EXTLIMIT n       Set max. bytes of extended memory used
  1899.      -EXTLOW addr      Set lowest extended memory address used
  1900.      -EXTHIGH addr     Set highest extended memory address used
  1901.      -ISTKSIZE n       Set size of interrupt stacks (1K blocks)
  1902.      -LDTSIZE n        Set number of LDT entries
  1903.      -NISTACK n        Set number of interrupt stacks
  1904.      -REALIMIT n       Set max. bytes of real memory used
  1905.      -SWITCH name      Select mode switch method (AUTO, AT, 386,
  1906.                 SURESWITCH, PS2, INBOARD, 6300, ACER,
  1907.                 VECTRA, VCPI, or FAST)
  1908.      -SWITCHFILE name  Select external switching .BIN file
  1909.      -XFERSIZE n       Set size of transfer buffer (1K blocks)
  1910.  
  1911.    Any LITE286 switch can be set on the DOS command line.  For 
  1912. example, the following runs MYPROG.EXE with a transfer buffer of 16 
  1913. KB:
  1914.  
  1915. C:\TEST>LITE286 -xfersize 16 myprog
  1916.  
  1917.    However, since normally we don't bother typing "LITE286" to run a 
  1918. program produced by BCC286, we need another way to set LITE286 
  1919. command-line options.  For example, the following is equivalent to 
  1920. the LITE286 command line just shown:
  1921.  
  1922. C:\TEST>set RUN286=-xfersize 16
  1923.  
  1924. C:\TEST>myprog
  1925.  
  1926.    Alternatively, if MYPROG should always be run with a LITE286 
  1927. switch such as -XFERSIZE 16, then the switch can be placed directly 
  1928. inside MYPROG.EXE, using the CFIG286 utility:
  1929.  
  1930. C:\TEST>cfig286 myprog.exe -xfersize 16
  1931.  
  1932. C:\TEST>myprog
  1933.  
  1934.    Note that the RUN286 environment variable affects all 286|DOS-
  1935. Extender Lite programs.  If you have several protected mode 
  1936. executables each requiring different LITE286 switches, you will 
  1937. probably want to use application-specific environment variables.  For 
  1938. example, if PHOO.EXE uses the LITE286 -XFERSIZE 16 switch, but 
  1939. BAR.EXE requires -XFERSIZE 32, you could place these switches in 
  1940. separate PHOO and BAR environment variables.  LITE286 will use 
  1941. whatever environment variable is specified in an %envvar switch:
  1942.  
  1943. C:\TEST>cfig286 myprog.exe %myprog
  1944.  
  1945. C:\TEST>set myprog=-xfersize 16
  1946.  
  1947. C:\TEST>myprog
  1948.  
  1949. or, using the examples of PHOO and BAR:
  1950.  
  1951. C:\TEST>cfig286 phoo.exe %phoo
  1952.  
  1953. C:\TEST>cfig286 bar.exe %bar
  1954.  
  1955. C:\TEST>set phoo=-xfersize 16
  1956.  
  1957. C:\TEST>set bar=-xfersize 32
  1958.  
  1959. C:\TEST>phoo
  1960.  
  1961. C:\TEST>bar
  1962.  
  1963.    Of course, you must have sufficient room in your DOS environment.  
  1964. If you receive an "Out of environment space" message, you need a 
  1965. larger DOS environment.  Add a line such as the following to your 
  1966. CONFIG.SYS file, and reboot:
  1967.  
  1968. SHELL=c:\dos\command.com /p /e:512
  1969.  
  1970.    Note that only LITE286 switches are processed in the LITE286 or 
  1971. application-specific DOS extender environment variables, or in the 
  1972. "configuration block" in an executable.  Any command line switches 
  1973. specific to your program must be handled by your program in the usual 
  1974. way.
  1975.  
  1976. --------------------------------------------------
  1977. The Phar Lap Application Program Interface (PHAPI)
  1978. --------------------------------------------------
  1979.  
  1980.    The full-blown 286|DOS-Extender SDK comes with extensive support
  1981. for the Phar Lap Application Program Interface (PHAPI), which
  1982. provides protected-mode DOS programs with a set of services in the
  1983. following areas:
  1984.  
  1985.    Creating and changing protected-mode selectors
  1986.  
  1987.    Communication between real and protected mode
  1988.  
  1989.    Dynamic Link Library (DLL) support
  1990.  
  1991.    Interrupt and exception handling
  1992.  
  1993.    DOS memory management
  1994.  
  1995.    80386 paging functions
  1996.  
  1997.  
  1998.    The following functions are part of PHAPI; prototypes for these
  1999. functions appear in PHAPI.H:
  2000.  
  2001. Selector and Memory Management
  2002. ------------------------------
  2003.  
  2004. DosAllocHuge            Allocate huge (> 64k) segment
  2005. DosAllocRealSeg         Allocate segment in conventional memory
  2006. DosAllocSeg             Allocate segment
  2007. DosCreateCSAlias        Create code alias to a data segment
  2008. DosCreateDSAlias        Create data alias to a code segment
  2009. DosFreeSeg              Free segment
  2010. DosGetBIOSSeg           Get selector to the BIOS data area
  2011. DosGetHugeShift         Get selector increment for huge segments
  2012. DosGetPhysAddr          Convert selector:offset to physical address
  2013. DosGetSegDesc           Get segment descriptor
  2014. DosLockSegPages         Lock pages of a segment
  2015. DosMapLinSeg            Map linear address
  2016. DosMapRealSeg           Map real mode address into protected mode
  2017. DosMapPhysSeg           Map physical address
  2018. DosMemAvail             Get amount of available extended memory
  2019. DosRealAvail            Get amount of available conventional memory
  2020. DosReallocHuge          Resize a huge segment
  2021. DosReallocSeg           Resize a segment
  2022. DosSetSegAttrib         Set access rights of a segment
  2023. DosUnlockSegPages       Unlock pages of a segment
  2024. DosVerifyAccess         Verify segment for read, write, execute
  2025.  
  2026. Interrupts and Exceptions
  2027. -------------------------
  2028.  
  2029. DosChainToProtIntr      Chain to a protected-mode interrupt handler
  2030. DosChainToRealIntr      Chain to a real-mode interrupt handler
  2031. DosGetExceptionHandler  Get exception (e.g., GP fault) handler
  2032. DosGetProtVec           Get protected-mode interrupt vector
  2033. DosGetRealProtVec       Get real- and protected-mode interrupt vector
  2034. DosGetRealVec           Get real-mode interrupt vector
  2035. DosIsProtIntr           Test if interrupt is from protected mode
  2036. DosIsRealIntr           Test if interrupt is from real mode
  2037. DosProtIntr             Generate a protected-mode interrupt from real mode
  2038. DosRealIntr             Generate a real-mode interrupt from protected mode
  2039. DosSetExceptionHandler  Set exception handler
  2040. DosSetPassToProtVec     Set interrupt vector to go to protected-mode handler
  2041. DosSetPassToRealVec     Set interrupt vector to go to real-mode handler
  2042. DosSetProtVec           Set protected-mode interrupt vector
  2043. DosSetRealProtVec       Set real- and protected-mode interrupt vectors
  2044. DosSetRealVec           Set real-mode interrupt vector
  2045. DosVProtIntr            Generate a protected-mode interrupt from real mode
  2046. DosVRealIntr            Generate a real-mode interrupt from protected mode
  2047.  
  2048. Mixing Real- and Protected-Mode Code
  2049. ------------------------------------
  2050.  
  2051. DosFreeProtStack        Free a protected-mode stack
  2052. DosFreeRealStack        Free a real-mode stack
  2053. DosProtFarCall          Call a protected-mode function from real mode
  2054. DosProtFarJump          Jump to protected mode from real mode
  2055. DosProtToReal           Convert a protected- to a real-mode address
  2056. DosRealFarCall          Call a real-mode function from protected mode
  2057. DosRealFarJump          Jump to real mode from protected mode
  2058. DosRealToProt           Convert a real- to a protected-mode address
  2059. DosVProtFarCall         Call a protected-mode function from real mode
  2060. DosVProtFarJump         Jump to protected mode from real mode
  2061. DosVRealFarCall         Call a real-mode function from protected mode
  2062. DosVRealFarJump         Jump to real mode from protected mode
  2063.  
  2064. Dynamic Linking
  2065. ---------------
  2066.  
  2067. DosEnumMod              Enumerate the currently-loaded modules
  2068. DosEnumProc             Enumerate the functions in a DLL
  2069. DosFreeModule           Free a DLL
  2070. DosGetModHandle         Get the module handle of a DLL
  2071. DosGetModName           Get the filename of a DLL
  2072. DosGetProcAddr          Get the selector:offset of a function in a DLL
  2073. DosGetRealProcAddr      Get the real-mode address of a function in a DLL
  2074. DosLoadModule           Load a DLL
  2075. DosSetProcAddr          Set the address of a function in a DLL
  2076.  
  2077. Miscellaneous
  2078. -------------
  2079.  
  2080. DosExecPgm              Start a new protected- or real-mode process
  2081. DosExit                 Exit from a program
  2082. DosExitList             Register an exit routine
  2083. DosGetMachineMode       Get processor mode
  2084. DosIsPharLap            Test if running under 286|DOS-Extender
  2085. DosPTrace               Debug a child program
  2086.  
  2087. ----------------
  2088. Chapter 4
  2089. Run-Time Library
  2090. ----------------
  2091.  
  2092. Keep in mind the following points when using the Borland C++ run-time 
  2093. library in protected mode:
  2094.  
  2095.  The farmalloc() call in protected-mode is not the same as large-
  2096.   model malloc().  farmalloc() takes an unsigned long parameter, and 
  2097.   can be used to allocate huge (> 64 KB segments); consequently, it 
  2098.   has additional overhead not present when using plain malloc().  
  2099.   Only use farmalloc() if you really want to allocate huge segments.
  2100.  
  2101.  The biosdisk() function is not supported, because 286|DOS-Extender 
  2102.   Lite does not support INT 13h (BIOS disk services) in protected 
  2103.   mode.
  2104.  
  2105.  The setvect() function is not supported.  setvect() is equivalent 
  2106.   to an INT 21h AH=25h (Set Interrupt Vector).  While INT 21h AH=25h 
  2107.   is fully supported under 286|DOS-Extender Lite, it is almost never 
  2108.   what one would want in a protected mode program.  All the most-
  2109.   common interrupts, such as Ctrl-C, Ctrl-Break, and Critical Error, 
  2110.   require that real mode interrupts be passed on to protected 
  2111.   mode.  This functionality is provided by the DosSetPassToProtVec() 
  2112.   function, available only with the full-fledged 286|DOS-Extender SDK.
  2113.  
  2114. ---------------
  2115. Further Reading
  2116. ---------------
  2117.  
  2118. Developers using 286|DOS-Extender Lite may be interested in reading 
  2119. the second edition of the book Extending DOS, edited by Ray Duncan. 
  2120. Chapter 4, on 16-bit protected-mode DOS extenders, contains over 70 
  2121. pages devoted largely to 286|DOS-Extender, including an extensive 
  2122. discussion of how to use Borland C++ with 286|DOS-Extender:
  2123.  
  2124. Ray Duncan et al., Extending DOS: A Programmer's Guide to Protected-
  2125. Mode DOS, Second Edition, Reading MA: Addison-Wesley, 1991, 538 pp., 
  2126. ISBN 0-201-56798-9.  
  2127.  
  2128. Other chapters describe 32-bit protected-mode DOS extenders, the VCPI 
  2129. and DPMI specifications, and other topics in protected-mode DOS 
  2130. programming.
  2131.  
  2132. ----------
  2133. Trademarks
  2134. ----------
  2135.  
  2136. 286|DOS-Extender(TM), 286|DOS-Extender Lite(TM) and 386|DOS-Extender(TM)
  2137.   are trademarks, and Phar Lap(R) is a registered trademark of 
  2138.   Phar Lap Software, Inc.
  2139. 386MAX(TM) is a trademark of Qualitas, Inc.
  2140. AutoCAD(R) is a registered trademark of Autodesk, Inc.
  2141. TASM(TM) is a trademark, and Borland(R) and Turbo Debugger(R) are 
  2142.   registered trademarks of Borland International, Inc.
  2143. COMPAQ(R) is a registered trademark of Compaq Computer Corporation.
  2144. DESQview(TM) and QEMM(TM) are trademarks, and DESQ(R) is a registered 
  2145.   trademark of Quarterdeck Office Systems.
  2146. PC/XT(TM) is a trademark, and IBM(R), AT(R), PS/2(R), and OS/2(R) are 
  2147.   registered trademarks of International Business Machines Corporation.
  2148. 287(TM), 386(TM), 387(TM), 486(TM), and i486(TM) are trademarks, and 
  2149.   Intel(R) is a registered trademark of Intel Corporation.
  2150. Interleaf Publisher(R) is a registered trademark of Interleaf, Inc.
  2151. Lotus(R) is a registered trademark of Lotus Development Corporation.
  2152. Mathematica(TM) is a trademark of Wolfram Research Inc.
  2153. Windows(TM) is a trademark, and Microsoft(R), MS(R), MS-DOS(R), and 
  2154.   CodeView(R) are registered trademarks of Microsoft Corporation.
  2155.