home *** CD-ROM | disk | FTP | other *** search
/ RBBS in a Box Volume 1 #3.1 / RBBSIABOX31.cdr / dull / dostips.doc < prev    next >
Text File  |  1985-08-19  |  57KB  |  1,397 lines

  1.                 Notes and Observations
  2.                        -
  3.                       on
  4.                        -
  5.             IBM PC-DOS and Microsoft MS-DOS
  6.                        -
  7.                  Releases 2.0 and 2.1
  8.                        -
  9.                   April, 1984
  10.  
  11.  
  12. This  document  is  a  collection  of  data  from various sources, including
  13. bulletin boards, magazines, seminar handouts, and independent research.
  14.  
  15. WARNING:  This  information  is provided without warranty of any kind.  Each
  16. individual must determine the applicability and accuracy ofthis  information
  17. to their specific environment.
  18.  
  19. If you have corrections, additions, or comments, please send them to:
  20.  
  21.                  John Chapman
  22.                   844 S. Madison St.
  23.               Hinsdale, Illinois   60521
  24.     Or, send  EMAIL  to  userid   [70205,1217]  on    CompuServ,
  25.     or       MAIL  to  userid    $AC        on    PCSHARE
  26.  
  27. BATCH PROCESSING
  28.  
  29. To  modify  the  DOS 2.0 command interpreter so that the default is echo off
  30. when a batch file is run,
  31.  
  32.    C>debug \command.com
  33.    -e1721 28 1f
  34.    -e364a 24 26 c6 06 6e 09 00 e9 19 e8
  35.    -w
  36.    Writing 4500 bytes
  37.    -q
  38.  
  39. The DOS Environment is accessible for use in BATs.
  40.  
  41. The  standard  keywords COMSPEC, PATH, PROMPT et al can all be read and set.
  42. New keywords can be set and checked within BATs.   The  keywords  are  saved
  43. across BAT executions.
  44.  
  45. For  instance BATs can check which screen is active using SET conventions as
  46. follows:
  47.  
  48.     . NOTE leading and trailing Percent signs
  49.     IF %SCREEN% == MONO GOTO COLOR
  50.     IF %SCREEN% == COLOR GOTO MONO
  51.     :COLOR
  52.     SET SCREEN=COLOR
  53.     . NOTE no spaces around '=' in SET
  54.     MODE CO80
  55.     EXIT
  56.     :MONO
  57.     SET SCREEN=MONO
  58.     MODE MONO
  59.     EXIT
  60.     . SCREEN is set and saved across BAT executions
  61.  
  62. Another example using a link convention allows BATs to call BATs:
  63.  
  64. *****CALL.BAT*****
  65.  
  66.     IF NOT %BATLABEL% == . GOTO %BATLABEL%
  67.     . note BATLABEL is assumed to be set to '.' as a null value
  68.     ECHO DO SOME STUFF HERE
  69.     SET BATCALR=%0
  70.     . give the called BAT my name to get back
  71.     . then leave word where to come back to
  72.     SET BATLABEL=RETURN
  73.     . set further parms to save %1 thru %9 if necessary
  74.     CALLED
  75.     :RETURN
  76.     ECHO FINISH UP HERE AFTER RETURN
  77.  
  78. PC/MS-DOS Tips (2.0/2.1)                        2
  79.  
  80. The DOS Environment is accessible for use in BATs. (Cont'd)
  81.  
  82. *****CALLED.BAT*****
  83.  
  84.     ECHO DO STUFF WE WERE CALLED TO DO
  85.     . return to caller
  86.     %BATCALR%
  87.     . separate keywords will be necessary if further calls
  88.     . will be made
  89.  
  90.  
  91. A note of caution (this is documented), the environment at boot time, is
  92. limited (I believe to only 128 bytes). If any resident modules are installed
  93. (i.e. PRINT, MODE, or GRAPHICS) the area cannot be expanded. You can SET
  94. enough variables from within AUTOEXEC.BAT to get enough space to get by.
  95.  
  96. I  would  also recommend setting up a set of conventions and preinitializing
  97. the  parms  you'll  use  to  '.';  Null  parameters  are  removed  from  the
  98. environment.
  99.  
  100. In summary -
  101.    The rules are simple
  102.     SET a parm without percent signs
  103.     refer to them by enclosing them in percent signs
  104.  
  105. I  hope  this  discovery  will  generate  a  lot  of  re-thinking  some  BAT
  106. techniques.
  107.  
  108. PC/MS-DOS Tips (2.0/2.1)                        3
  109.             Current MSDOS 1.xx - 2.xx Disk formats
  110.  
  111.                 (T. Jennings 19 Aug 83)
  112.  
  113.     Disk Type               Type Code
  114.     .......................................................
  115.     Single Density Single Sided 8"       (SD128)
  116.    **** Double Density Single Sided 8"       (DD1024)
  117.    **** FIDO's 8" Double Density       (DD1K)
  118.     Double Density Double Sided 8"       (DD1024-2)
  119.     IBM Displaywriter System disk       (SD256)
  120.     IBM Displaywriter System disk       (DD256-2)
  121.     IBM PC 8 Sector Single Sided       (IBM8)
  122.     IBM PC 9 Sector Single Sided       (IBM9)
  123.     IBM PC 8 Sector Double Sided       (IBM8-2)
  124.     IBM PC 9 Sector Double Sided       (IBM9-2)
  125.     Single Density Double Sided 8"       (SD128-2)
  126.  
  127.    **** Never did get Microsoft to figure out which one these
  128.     is the "correct" 8 inch format. Who knows.
  129.     Type      Dir  Disk     Fats Blk  Res    Sec      FAT
  130.     Code      Size Size          size secs size      ID
  131.     .....................................................
  132.     SD128       68    251K     2     512  1     128      FE
  133.     DD1K      192    660K     2    1024  1    1024      FE
  134.     DD1024       96    612K     2    1024  1    1024      FE
  135.     DD1024-2  192  1232K     2    1024  1    1024      FF
  136.     SD256       80    287K     2     512  2     256      FA  Note 1
  137.     DD256-2   172  1001K     2    1024  2     256      FB  Note 2
  138.     IBM8       64    162K     2     512  1     512      FE
  139.     IBM9       64    180K     2     512  1     512      FC
  140.     IBM8-2      112    320K     2    1024  1     512      FF
  141.     IBM9-2      112    360K     2    1024  1     512      FD
  142.     SD128-2    68         2     512  4     128      FC
  143.  
  144.     Type      trks secs res  sec  FAT  dir    1st  2nd  1st  1st  totl num.
  145.     Code           trk  secs size size size FAT  FAT  dir  data secs heads
  146.     ......................................................................
  147.     SD128      77   26    1      128    6  17     1    7   13   30   2002  1
  148.     DD1024      77    8    1     1024    1   3     1    2    3    6    616  1
  149.     DD1024-2  77    8    1     1024    2   6     1    3    5   11   1232  2
  150.     SD256      77   15   17      256    4  10     2    6   10   20   1155  1
  151.                                     Note 1
  152.     DD256-2   77   26   54      256    6  20     2    8   14   34   4004  2
  153.                                     Note 2
  154.     IBM8      40    8    1      512    1   4     1    2    3    7    320  1
  155.     IBM9      40    9    1      512    2   4     1    3    5    9    360  1
  156.     IBM8-2      40    8    1      512    1   7     1    3    5   10    640  2
  157.     IBM9-2      40    9    1      512    2   7     1    3    5   12    720  2
  158.     SD128-2   77    26   4      128  12  17     4   16   28   45   4004  2
  159.  
  160.    Note 1:
  161.     15 sector bias in BIOS
  162.    Note 2:
  163.     52 sector bias in BIOS
  164.  
  165. PC/MS-DOS Tips (2.0/2.1)                        4
  166.               Additional feature in DEBUG command
  167.  
  168. There  is  a compare feature in DEBUG that is not in the documentation.  Two
  169. blocks of memory can be compared, byte by byte with the following command:
  170.  
  171.       -C AD1 AD2 AD3
  172.  
  173. DEBUG  will  compare  the memory block from AD1 to AD2 with the memory block
  174. starting at AD3.  The results appear in a table showing both blocks side  by
  175. side with the addresses and the corresponding contents.
  176.  
  177.              (from IBM.PC Users Group of Winnipeg)
  178.  
  179. PC/MS-DOS Tips (2.0/2.1)                        5
  180.  
  181.                  Program File Formats
  182.  
  183. The order of the segments in memory is determined by the linker; and all the
  184. segments  are  contiguous,  unless  you do some really determined and tricky
  185. hacking.  Supposedly, the linker determines the order  of  the  segments  by
  186. putting  them  in  "alphabetical  order by segment name", or at least that's
  187. what the documentation says it's supposed to do; but I've found that it puts
  188. them in the order in which they're encountered in the program  source  code,
  189. unless  you  create  a  dummy  file (see LINK instructions) with a different
  190. sequence and make it first in the LINK list of OBJ  modules.   (I  generally
  191. put  them  in source in the sequence code, data, stack; they always come out
  192. in that order, regardless of segment names, unless I  use  the  dummy  file.
  193. Let's assume that sequence for the remainder of this discussion.)
  194.  
  195. With an .EXE file, just before execution, the registers are as follows:
  196.  
  197.    AX         - ostensibly per doc, zero; seems to contain the number
  198.         of characters in the command tail, though
  199.  
  200.    BX:CX     - 32-bit number showing load module memory size in bytes
  201.         (good for dynamically allocating memory)
  202.  
  203.    DX         - zero
  204.  
  205.    SS:SP     - if you defined a stack segment, these are loaded
  206.         accordingly; if not, SS=CS, SP=0FFFFH or end of
  207.         memory
  208.  
  209.    DS and ES - SEGMENT address of "program header" (see below)
  210.  
  211.    CS:IP     - far address of label in "END" statement of program
  212.  
  213. The  program  header is the standard 256-byte .COM file "header", similar to
  214. what you would expect to see  at  00-FFH  in  CP/M  2.x  (but  see  doc  for
  215. important differences!).  Therefore, DS = CS - 10H (which is 100H divided by
  216. 10H)  if the code seg is the first (owest) in memory, because it points to a
  217. location 100H before the start of the code seg.
  218.  
  219. PC/MS-DOS Tips (2.0/2.1)                        6
  220.                  Program File Formats   (Cont'd)
  221.  
  222. Now, if CS is, say, 9E3H when you come up, then DS and ES will contain 9D3H.
  223. (Remember,  though, that your code thinks it starts at 9E3:0, zero being the
  224. address you specified in your END directive,  and  the  instruction  pointer
  225. will  actually  contain  zero.)  These values have nothing at all to do with
  226. the place at which your data seg is located; they  point  at  that  "program
  227. header".   At  location  9D3:80 (DS:80) is the command tail, if you're gonna
  228. reference that; its length is in AX (I believe) and is also  pointed  to  by
  229. the  expression  DS:80  (just  like  CP/M; data starts at 81H), or to say it
  230. another way, in this case absolute memory location  09DB0  (09D30+80).   But
  231. your  code  segment  is, say, 400H long, and the linker knew that 'cause the
  232. assembler told it so in the seg, the instructions
  233.  
  234.        MOV       AX,DATASEG
  235.        MOV       DS,AX
  236.        MOV       ES,AX
  237.  
  238. (where  DATASEG is the name of your data segment) will have been resolved by
  239. the linker in this way; the first instruction of those three was interpreted
  240. by the assembler as an immediate move, but the "data" to be  moved  into  AX
  241. was marked as relocatable.  The linker leaves instructions for the loader to
  242. add 9E3H (or whatever address the loader decided was a good place to put the
  243. program)  to  the  value  of  the  "constant" DATASEG, which is equal to 40H
  244. (400H/10H) because it's being "loaded" into a segment register, and when you
  245. look at that instruction under DEBUG it would say MOV AX,0A23H.  (Obviously,
  246. this is the process of address  resolution.)   In  absolute  addresses,  the
  247. codeseg  starts  at  09E30H,  and  the dataseg 400H later at 0A230H; in 8086
  248. shorthand that's 9E3:0 and A23:0 respectively.  (This assumes  the  stackseg
  249. is   last,   say  at  A98:0;  that  would  imply  that  your  data  seg  was
  250. (0A98H-0A23H)*10H, or 750H, in length.)
  251.  
  252. Almost all instructions accessing data use DS as "base" register, unless you
  253. override  that  with  a  prefix  (as in MOV AX,ES:BLKCTR).  All instructions
  254. accessing storage require one of the segregs as  "base"  register.   (String
  255. primitives  ALWAYS  work  with  DS  and/or  ES  and can't be overridden by a
  256. prefix; instructions using BP as an  "index"  are  relative  to  SS,  unless
  257. overridden  by  a  prefix;  otherwise,  it's  DS  when  not  overridden.  Be
  258. careful!)
  259.  
  260. PC/MS-DOS Tips (2.0/2.1)                        7
  261.  
  262.                  Program File Formats   (Cont'd)
  263.  
  264. In BAL, you give the assembler a USING statement; that tells it that offsets
  265. will  be  computed relative to the first operand of the USING statement, and
  266. tells it to use  the  second  operand  as  "base"  register  in  base+offset
  267. instructions.   The  code  won't work properly until you load the address of
  268. the first operand into the register named by the second operand.   In  8086,
  269. you  give  the  assembler  an ASSUME statement; for instructions using CS as
  270. "base" (segment) register (all of them), such  offsets  will  be  calculated
  271. from the point named as xyz in the statement "ASSUME CS:xyz, DS:abc,ES:def";
  272. for  instructions  which  use  DS  (such as MOV AX,BLKCTR), the value of the
  273. offset of BLKCTR is computed relative to  label  abc;  for  ES  instructions
  274. (when  you use a segment override prefix, as in MOV AX,ES:BLKCTR), offset is
  275. computed relative to "def".  Then, if you hav that (for  example)  DS:offset
  276. points to the absolute location of BLKCTR, you'll be moving something random
  277. into  your  AX  register.  With .COM files, CS=DS=ES at startup; note that a
  278. typical    .COM    file    ASSUME    statement     looks     like     ASSUME
  279. CS:CODESEG,DS:CODESEG,ES:CODESEG,SS:CODESEG (whoops, one more)
  280.  
  281. But as you can see from the preceding stuff, with .EXE files DS and ES start
  282. out  with  values  which  don't  point  at your data at all.  You have to do
  283. something like MOV AX,abc!MOV DS,AX!MOV ES,AX to put  coherent  values  into
  284. the  segregs,  just  as you have to do something like BALR 4,0!BCTR 4,0!BCTR
  285. 4,0 to put a coherent value into the base reg in BAL.  That is, with an .EXE
  286. file, you tell the assembler to  use  DATASEG  as  the  reference  point  to
  287. compute  an  offset from (with the ASSUME statement); and then you must make
  288. sure you load DS with a value that will, in combination  with  the  computed
  289. offset, point at the right data.
  290.  
  291. One  more  example,  then I'll stop.  Let's take a BAL program and specify a
  292. code "segment" 4096 bytes long, a data "segment"  4096  bytes  long,  and  a
  293. "stack  segment" after that.  In order to be able to access all of that data
  294. in that way, you'd need three base registers; let's use 3, 4  and  5.   With
  295. BAL, you have to figure the addresses yourself, so we get something like:
  296.  
  297.    PGM       START   0 BEGIN   STM     14,12,12(13)
  298.        BALR    3,0
  299.    DTSEG   EQU       START+4096
  300.    STSEG   EQU       START+8192
  301.        USING   *,3
  302.        USING   DTSEG,4
  303.        USING   STSEG,5
  304.    START   ST       13,SAVEAREA+4
  305.        LA       13,SAVEAREA
  306.        LA       4,4096(3)
  307.        LA       5,8192(3)
  308. That is, if I remember my BAL. You get the idea.
  309.  
  310. PC/MS-DOS Tips (2.0/2.1)                        8
  311.  
  312.                The CTTY Command and Basic Feature
  313.  
  314.                    (from Tom Jennings)
  315.  
  316. The  DOS  manual explains that the command is simply CTTY device-name.  This
  317. will transfer control from the keyboard  and  screen  to  that  device.   It
  318. suggests  that  LPT1:  is  not  a  ood  idea  since the printer communicates
  319. (mostly) one way.  What this really leaves is COM1:, COM2: and AUX:  I  very
  320. cleverly tried typing CTTY COM1: It does do something, it kills the keyboard
  321. and  a  cold BOOT is necessary to restart.  Well, that wasn't it.  Something
  322. must occur prior to the CTTY command.  Being  strickly  a  seat-of-the-pants
  323. type,  I  set  the  HAYES to ANSWER and called in.  Nice, I had a connection
  324. (CARRIER/carrier).  I rushed over to the PC keyboard and  typed  CTTY  COM1:
  325. and  the screen went dead.  So, what else is new....But, on my other SYSTEM,
  326. (other end of the office), the prompt A> appeared.  I sat and typed  on  the
  327. terminal just as though I was sitting in front of the IBM.
  328.  
  329. Well, what do you know?
  330.  
  331. 1) Commands are limited to what the terminal keyboard can reproduce i.e.  ^C
  332. for CTRL-BREAK but not CTRL-ALT-DEL (as if you would want that one anyway).
  333.  
  334. 2) Going to BASIC cuts you off.  SYSTEM control returns to the keyboard.
  335.  
  336. 3)  Most  commands work except COPY as it relates to CON: or COM1: COPY from
  337. disk to disk worked O.K.
  338.  
  339. 4)  This  means  is  total  control  from  outside  while  in  DOS only on a
  340. line-by-line basis.  Anything which relies on screen mapping will not  work.
  341. (Run  Norton's  DISKMAP  from  the  terminal  and  the map appears on the PC
  342. screen.)
  343.  
  344. You  may  be  wondering  why  all  this verbage.  Well....  the result of my
  345. efforts is a BASIC program called RING.BAS which will set up  the  HAYES  to
  346. patiently  look  for an incoming ring, and very politely turn SYSTEM control
  347. over to the caller.  Oh, I forgot to  mention  the  BASIC  program  must  be
  348. called  from  a  BATCH file called OUTSIDER.BAT.  When RING goes back to the
  349. SYSTEM, the next command is CTTY COM1: Slick, huh?  RING will even write the
  350. BATCH file for you.  Just take a look  at  the  internal  documentation  for
  351. additional information.
  352.  
  353. Note:  Tom Jenning's 'FIDO' board is at (415) 864-1418
  354.  
  355. PC/MS-DOS Tips (2.0/2.1)                        9
  356.  
  357.            DOS 2.0 HAS PROBLEMS WITH REDIRECTION OF I/O
  358.  
  359. There  are  problems  in  DOS 2.0 with the redirection of I/O and piping for
  360. programs that use the original DOS 1.1 INT  21  function  calls  for  input.
  361. This  problem  is  readily  apparent to users of C language packages such as
  362. Computer Innovation C-86, Lattice C, or Microsoft C (you'd think they  would
  363. get it right!).  One problem is that all output to the screen is redirected,
  364. even keyboard echo.  Correct operation would redirect all program output for
  365. the  screen  (stdout) to the specified >file, but the echo of keyboard input
  366. would still be sent to the screen.  Instead, both the keyboard echo and  the
  367. program  output are sent to the redirected >file.  Thus, if you run programs
  368. such as the CAT.C (K&R,page 154) example  that  Microsoft  distributes  with
  369. their C; or COPYIO.C (K&R,page 15) with the output redirected to a file, you
  370. will get the following results:
  371.  
  372. 1.   Under  DOS  1.1, keyboard input is echoed to the screen as you type and
  373. each line appears in the >file once as expected.
  374.  
  375. 2.  Under DOS 2.0, keyboard input is not echoed to the screen, but each line
  376. appears in the >file twice!
  377.  
  378. This  situation  is  handled correctly in DOS 2.0 if the new INT 21 function
  379. call 3F is used.  This can be demonstrated by redirecting output for the DOS
  380. 2.0 function MORE - it works as desired.
  381.  
  382. The redirecting of input to these programs doesn't work properly either.  If
  383. the file has not been edited with debug to end with a control-Z, the program
  384. will  hang  up at the end of the <input file.  You must reboot the system to
  385. continue!  Also, if you pipe the output of the first program into  a  second
  386. program,  the final output will contain each line four times, doubled spaced
  387. after the second lie!  These problems do not occur for programs that use the
  388. new DOS 2.0 calls for I/O, such as SORT and MORE.
  389.  
  390.     The question now is how do you fixup C programs to run under DOS 2.0
  391. and  not  redirect  keyboard echo to the stdout file?  The easiest way for C
  392. compilers that include  their  own  redirection  code  is  to  change  their
  393. redirection symbols from <, >, and >> to something else.  Then DOS 2.0 won't
  394. do the redirection, so the C code will be able to do it correctly.  With the
  395. Microsoft  C  compiler, this is easily accomplished by modifying three lines
  396. of code in MAIN.C.  A good choice is to modify MAIN.C so that  it  redirects
  397. on  the  symbols {, , and .  The only restriction is that these symbols then
  398. should not be used in filenames.  With these changes, the user can choose to
  399. let either DOS <, >, >> or C {, .  do the redirecting.  The modified version
  400. of MAIN.C is compiled to obtain a new MAIN.OBJ, which can either be put into
  401. the library MC.LIB to  replace  the  original  MAIN  by  using  the  LIB.EXE
  402. utility,  i.e.   LIB  MC.LIB  MAINMAIN  or it can be kept separate.  If kept
  403. separate, remember to include it in the list of .OBJ files specified in  the
  404. LINK call, i.e.  LINK cmain myprogram.
  405.  
  406.     The three lines to change in Microsoft C's MAIN are:
  407.          case '{':
  408.          case ' ':
  409.          if (*line == ' ')
  410.  
  411. PC/MS-DOS Tips (2.0/2.1)                        10
  412.  
  413.  
  414.     The  following  is  a summary of some undocumented DOS 2.0 functions
  415. which can be invoked through interrupt 21H.  The information provided herein
  416. have inaccuracies, so use it at our own risk!  It is correct to the best  of
  417. my knowledge.  See the section in your DOS 2.0 manual entitled "Invoking DOS
  418. Functions"  for further information.  The function number provided below for
  419. each operation is to be placed in the AH register as described  in  the  DOS
  420. manual.  All numbers shown are in hex.
  421.  
  422.    FUNCTION           DESCRIPTION
  423.  
  424.       37       This interrupt is used to change incompatible
  425.            configuration parameters to allow for switch
  426.            indicators and whether hardware devices are
  427.            available at every level of the tree directory.
  428.  
  429.            Usage:  MOV       AH, 37
  430.                MOV       AL, func           ; function code
  431.                MOV       DL, data
  432.                INT       21H
  433.            ; read function data is returned in DL
  434.  
  435.            Function code for AL:
  436.            0 - Return the DOS switch character in DL.
  437.                Many systems might return "-".
  438.            1 - Make the character in DL the switch character.
  439.            2 - Read the device availability byte into DL. A
  440.                0 means devices that devices must be accessed
  441.                in file I/O calls by /DEV/device. A non-zero
  442.                value means that devices are accessible at
  443.                every level of the directory tree (e.g., PRN
  444.                is the printer and not a file PRN).
  445.            3 - Set the device availability byte to the
  446.                contents of DL.
  447.  
  448.            Possible errors returned in AL:
  449.            FF - Illegal function code specified in AL.
  450.  
  451.       1F (?)       Retrieve the pointer to the default drive parameter block.
  452.  
  453.            Usage:  MOV       AH, 1F
  454.                INT       21H
  455.            ; address of drive parameter block is returned in DS:BX
  456.  
  457. PC/MS-DOS Tips (2.0/2.1)                        11
  458.       32 (?)       Retrieve the pointer to the drive parameter block
  459.            for the drive number in DL, where 0 = default drive,
  460.            1 = drive A:, 2 = drive B:, etc.).
  461.  
  462.            Usage:  MOV       AH, 32h
  463.                MOV       DL, drivenum
  464.                INT       21H
  465.            ; address of drive parameter block is returned in DS:BX
  466.            ; AL contains FF if the drive # in DL is invalid.
  467.  
  468.       F8 (?)       Set OEM handler for INT 21H calls from F9 through FF
  469.            to DS:DX. To reset these calls, pass DS and DX with FFFF.
  470.            DOS is set up to allow ONE handler for all 7 of these
  471.            calls. Any call to these handlers will result in the
  472.            carry bit being set and AX will contain 1 if they are
  473.            not initialized. The handling routine is passed all
  474.            registers just as the user set them. The OEM handler
  475.            routine should be exited through an IRET.
  476.  
  477.            Usage:  LDS       DX, handleaddr
  478.                MOV       AH, F8h
  479.                INT       21H
  480.       4B       Load and possibly execute a program (EXEC). This call
  481.            is PARTIALLY documented in the IBM DOS 2.0 manual, but
  482.            several function call values (for register AL) are
  483.            omitted. They are:
  484.  
  485.                1 - Create the program segment prefix and
  486.                    load the program, but do not begin
  487.                    execution. The CS:IP and SS:SP of the
  488.                    program are placed in the area provided
  489.                    by the user.
  490.  
  491.                    +-------------------------------+
  492.                    | Word segment addr of environ. |
  493.                    +-------------------------------+
  494.                    | Dword ptr to cmd line at 80h  |
  495.                    +-------------------------------+
  496.                    | Dword ptr to default FCB to   |
  497.                    | be passed at 5Ch.           |
  498.                    +-------------------------------+
  499.                    | Dword ptr to default FCD to   |
  500.                    | be passed at 6Ch.           |
  501.                    +-------------------------------+
  502.                    | Dword value of SS:SP returned |
  503.                    +-------------------------------+
  504.                    | Dword value of CS:IP returned |
  505.                    +-------------------------------+
  506.  
  507.                2 - This function still remains a mystery.
  508.    PC/MS-DOS Tips (2.0/2.1)                        12
  509.  
  510.       4E       Find first matching file (FIND FIRST). This function
  511.            is PARTIALLY documented in the IBM DOS 2.0 manual.
  512.            The description of what is returned in the DTA where
  513.            the first 21 bytes are "reserved for DOS use on
  514.            subsequent find next calls" contain the following
  515.            in this order:
  516.  
  517.                1 byte  - attribute byte of search
  518.                1 byte  - drive used in search
  519.                11 bytes- The search name used
  520.                2 bytes - Word value of last entry
  521.                4 bytes - Dword pointer to this DTA
  522.                2 bytes - Word directory start
  523.                -----------------------------------
  524.                { The documented bytes follow here
  525.                  such as attribute found, file's
  526.                  time, date, size, and name found.
  527.  
  528.  
  529.       50       Define the current DTA (?) - this is all I know...
  530.       51       Retrieve current DTA (?)
  531.       52       Retrieve "IVARS" (?)
  532.       53       Define something about a DTA (?)
  533.       55       Duplicate a DTA (?)
  534.  
  535.        The  DOS  critical  section  flag  may be interrogated from within an
  536. interrupt handler before requesting DOS services:
  537.  
  538.          MOV AH,34h
  539.          INT 21h
  540.  
  541.        returns in ES:BX the address of a byte indicating (when set) that DOS
  542. is in an uninterruptible state, and no DOS calls should be made.
  543.  
  544. PC/MS-DOS Tips (2.0/2.1)                        13
  545.  
  546.    To access DOS' PRINT capabilities:
  547.          MOV AH,func
  548.          INT 2Fh
  549.      Where:
  550.  
  551.          AH = 0    adds the file specified by DS:DX to the
  552.                print queue.  DS:DX must point to valid
  553.                opened FCB.
  554.  
  555.          AH = 1    cancels the file indicated by DS:DX.
  556.                DS:DX must point to an FCB, opened or
  557.                unopened.  The drive byte must not be 0.
  558.                Wildcards are restricted: ? is okay, *
  559.                isn't.
  560.  
  561.          AH > 1    do nothing.
  562.     Return with registers set as follows:
  563.                DS,SI,DI,CX preserved, all others destroyed.
  564.                AH = number of files currently in queue.
  565.                AL = for AH=0, return 1 if queue was
  566.                 full.  For all other cases, return 0.
  567.                ES:BX = pointer to list of 10 FCBs in
  568.                 queue, 38 bytes/FCB.  If the first
  569.                 byte of an FCB is -1, that FCB is
  570.                 unused.
  571.  
  572.                ES:DX = pointer to currently printing
  573.                 FCB.  If the queue is empty, DX = -1.
  574.  
  575. PC/MS-DOS Tips (2.0/2.1)                        14
  576.     An Operating System Dialog - PC/MS-DOS
  577.  
  578.        This  is  a list of PCDOS and MSDOS peculiarities, etc.  You will
  579. have to guess from the text what the  particular  questions  were,  but  you
  580. systems programmers will find it worth your while to rummage through it all.
  581.  
  582.    There  is a problem of compatibility between MS-DOS and IBM PC-DOS having
  583. to do with FCB Open and Create which has finally been tracked.  The IBM 1.0,
  584. 1.1, and 2.0  documentation  of  OPEN  (call  0FH)  contains  the  following
  585. statement.
  586.  
  587.        "The current block field (FCB bytes C-D) is
  588.         set to zero [when an FB is opened]."
  589.  
  590.    This statement is NOT true of MS-DOS 1.25 or MS-DOS 2.00.  The difference
  591. is  intentional,  and  the  reason  is CP/M 1.4 compatibility.  Zeroing that
  592. field is not CP/M compatible.  Some CP/M programs will not run when  machine
  593. translated  if  that  field  is zero ed.  The reason it is zeroed in the IBM
  594. versions is that IBM specifically requested that it be zeroed.  This is  the
  595. reason  for  the  complaints  from  some  vendors  about  the  fact that IBM
  596. MultiPlan will not run under MS-DOS.  It is probably the  reason  that  some
  597. other IBM programs don't run under MS-DOS.
  598.  
  599.    PROGRAMMERS NOTE:
  600.  
  601.        Do  what  all MS/PC-DOS Systems programs do: Set every single FCB
  602. field you  want  to  use  regardless  of  what  the  documentation  says  is
  603. initialized.
  604.  
  605.        a)  It  seems  there  is  a maximum of 19 handles, no matter what the
  606. files parameter is set to.  Is this really the case?  What does one gain  by
  607. setting files to less than 19?  Is memory for handles allocated dynamically?
  608.  
  609.        There  is  a maximum of 20 handles per process no matter what the
  610. files parameter is set to.  There has to be a table in your  process  header
  611. for  your  handles, there is a limited amount of space down there.  40 bytes
  612. or so are taken up by each system FCB, setting files to less than 20 saves a
  613. little bit of memory.  Memory for handles is not allocated  dynamically,  in
  614. general  an  attempt to do so would fail anyway.  Recall that .COM files and
  615. most .EXE files are given the biggest piece of memory possible  w  hen  they
  616. are  EXECed  because  the  DOS cannot make assumptions about how much memory
  617. these programs really use.  This means they typically get ALL  of  the  free
  618. memory,  that  means  there  is no free memory to allocate dynamically.  You
  619. will find that almost a  ll  operating  systems  (CP/M  is  about  the  only
  620. exception)  have a limit on the number of open files.  MS-DOS has a limit of
  621. 20.  CP/M has no such limits because it requires the user to  keep  FCBs  in
  622. his own address space, managing FCBs is a pain.  You get si mplicity and you
  623. give  up  very  little.  What program needs more than 20 open files?  If you
  624. can think of one, it is  probably  a  poorly  written  program  in  that  it
  625. probably  only  needs a few open files at a time and doesn't bother to close
  626. files after it's d one with them.
  627.  
  628. PC/MS-DOS Tips (2.0/2.1)                        15
  629.  
  630.        b)  Execing  a program eats 5 (I think) handles per try.  Is this the
  631. passing of parent's environment that is  mentioned  (very  briefly)  in  the
  632. documentatio  n?   What  are these handles?  They don't seem to be allocated
  633. with system  calls,  either.   Is  that  true?   std-in,  std-out,  std-err,
  634. std-aux,  std-prn.   I suppose you would like your program to be able to use
  635. the 1-12 system calls?  That means there have to be 5, the first  three  are
  636. standard UNIX style fair and are required for the software tools approach to
  637. programming.   Std-aux and Std-prn are required for system calls 3,4, and 5.
  638. Just because you are handed these default handles  doesn't  mean  you  can't
  639. close them.
  640.  
  641.        "...  1) what exactly is meant by the dos being in an unstable state.
  642. (This  is  what  the  documentation  says  happens  if one returns to a user
  643. program directly from an int 24 handler.)..."
  644.  
  645.    It  means  that  the DOS has the notion of an error being in effect.  All
  646. printer echoing is turned off, and some other  stuff  doesn't  work.   Also,
  647. there  are dirty buffers that are not correctly flushed out.  Thus the disks
  648. may not be consistent.
  649.  
  650.        "...   2)  my  experimentation  shows that an abort from a hard error
  651. handler causes an int 22 without the value for int 22 being  sucked  out  of
  652. the  program  header.   every  other  way out of a program uses he terminate
  653. address in the header.  is this  difference  intentional?   Why?   DOes  one
  654. expect  the  value  at  int  22 to be different from the value in the header
  655. ever?..."
  656.  
  657.    False.   No  INT 22h is ever issued.  The header is only used to save the
  658. previous process' vectors.  The address contained in INT 22 is  saved  in  a
  659. temp spot, the contents of INTs 22-24 are restored from the header, and then
  660. an  indirect  jump  is  taken  th rough the temp location.  Certain programs
  661. (such as COMMAND) may want to intercept  themselves  from  terminawill  then
  662. attempt  to  write  it out, causing a write-protect error.  If you catch the
  663. INT 24 and do not return, the dirty b uffer still exists.  To clear out  the
  664. dirty  buffer,  you MUST return from the INT 24 saying to abort the process.
  665. You can then catch the terminate and restore your stack (you will be running
  666. on your parent's stack).
  667.  
  668.        "...   1)  Why does PCDOS exec function 3 (overlay) demand that there
  669. be some free memory that it can allocate...."
  670.  
  671.    It doesn't.  IBM specifically requested that the Exec code be overlayable
  672. in  the  MSDOS.  As a result, it lives in the transient piece of COMMAND.COM
  673. and gets loaded when needed: thus the requidement for enough free  space  to
  674. laod the Exec loader (about 1.5K).
  675.  
  676.    Under  other  MSDOS's  there  is  no such problem as the Exec system call
  677. lives in system space.  A general rule of thumb is: if you are not going  to
  678. use  some  space, free it.  You can do this either via SetBlock system call,
  679. or by twiddling the EXE file he ader.  You should avoid .COM format files.
  680.  
  681. PC/MS-DOS Tips (2.0/2.1)                        16
  682.  
  683.        "...  what happens if I try to overlay an .EXE file with the high/low
  684. switch set to load the thing for high memory..."
  685.  
  686.    Nothing.   The  HIGH/LOW  switch  is  only  for process creation, not for
  687. overlays.
  688.  
  689.        "...  Are all these answeres the same for MSDOS?..."  [Yes.]
  690.  
  691.        "...  zeroing of the current record field ..."
  692.  
  693.    That  incompatability  existed  between  1.1  PC-DOS and 1.25 MSDOS.  2.0
  694. versions of both function identically (like 1.1 PC-DOS).
  695.  
  696.    The Shell command on PC-DOS 2.0 works just fine.
  697.  
  698.        CONFIG.SYS
  699.            shell = b:\command.com b:\ /P
  700.  
  701.    Putting  a disk with command.com in drive B: when the system boots causes
  702. COMMAND to be read from drive B: and  the  COMSPEC  in  the  environment  is
  703. "B:\COMMAND.COM".   If  you  are  having  trouble it's because you are doing
  704. something wrong.  Recall that your g iven COMSPEC is checked, if you give it
  705. a bad one it will try to go back to the default which is the root  directory
  706. on  the default drive.  Recall also that this is an undocumented 2.0 feature
  707. so even if it doesn't work nobody is going  to  be  all  that  ho  t  to  do
  708. something about it.
  709.  
  710.     My  error  on  the shell stuff, IBM hid it real well.  The "b:\" is also
  711. documented on page 10-9 (the [d:][path] part).  They did an equally poor job
  712. here.
  713.  
  714.    The  /P  and  the  path spec have absolutely nothing to do with the SHELL
  715. command, they are arguments to  command.   Expecting  SHELL  to  know  stuff
  716. particular  to  command  is not reasonable because you are not restricted to
  717. running command as your top level she ll.  You can run  DEBUG  as  your  top
  718. level shell by saying
  719.  
  720.        SHELL = debug.com
  721.  
  722.    But  watch  out!!  debug is not designed to run as a top level shell.  if
  723. you ever say "q" to this debug the system will crash.  Command on the  other
  724. hand is smart enough to run as a top level shell.  If you give the /P switch
  725. to  it  Command  does  some specia l things to insure that typing EXIT to it
  726. will not cause the system to crash as with debug.  There  is  absolutely  no
  727. way  for  command to assume the /P switch because he must run as a top level
  728. shell, and as a utility.  The smart  user  has  to  tell  him  what  to  do.
  729. Similarly the "b:\" tells command where to look for himself.  For instance:
  730.  
  731.        SHELL = A:\BIN\COMMAND.COM D:\COMMAND\BIN /P
  732.  
  733.    The   "A:\BIN\COMMAND.COM"  tells  SYSINIT  where  to  load  the  initial
  734. command.com, the "D:\COMMAND\BIN" tells command where to  look  for  himself
  735. when  he  needs  to  locate  his  transient.   As  you  can see they are not
  736. restricted to being the same things.  I suggest you foreward any  complaints
  737. about the manual to [no address given]
  738.  
  739. PC/MS-DOS Tips (2.0/2.1)                        17
  740.  
  741.     The volume ID attribute is very special, and is treated differently from
  742. all  the  other  attributes.   It is very "sticky", in order to find one you
  743. must look for it and it alone.  And when you do look for it, you  find  only
  744. it and nothing else.
  745.  
  746.    The  volume  ID is constrained to be in the ROOT directory, and there can
  747. be only one file in the ROOT with the attribute.  The FCB flavor calls  have
  748. special code to enforce these rules.
  749.  
  750.    The  new  calls were supposed to enforce the same rules, but they are not
  751. working correctly, and unexpected results are possible.  You should use  the
  752. old FCB calls to diddle with volume ID for the moment.
  753.  
  754.    Thanks for the info.  The causes of your problems are:
  755.  
  756.    (a)  ^Z  on  output to a device in cooked mode will terminate the output.
  757. This is for CPM-compatability: you don't want stuff after the ^Z  output  to
  758. your printer for example.
  759.  
  760.        As  a  result COMMAND.COM issues a write to stdout and then checks to
  761. see if the number written is equal to the number requested.  If they are not
  762. the same, then a redirection error is  assumed.   ECHO  ^Z  is  supposed  to
  763. output  a  single cha racter.  It outputs NO characters and thus the strange
  764. message.
  765.  
  766.        Programs  that  use old function calls, get redirected, and then read
  767. more than is expected will behave bizarrely: how do you indicate  EOF  on  a
  768. read-byte-from- console system call?  I believe that it returns ^Z.  Most of
  769. these programs we re never expecting to get redirected and thus, the failure
  770. to handle the boundary conditions properly.
  771.  
  772.    (b)  The  main  crock  about  CP/M  is  that the extention on a file name
  773. determined the  type  of  the  file.   This  is  bogus:  a  file  should  be
  774. distinguished by its contents, not by its name.  When you are loading a file
  775. with  the name *.EXE, it d oes NOT assume that it is an EXE format file.  It
  776. looks at the first two bytes for a signature telling it that it  is  an  EXE
  777. file.  If it has the proper signature, then the loa proceeds.  otherwise, it
  778. presumes the file to be a COM- form at file.
  779.  
  780.        If  the  file has the EXE signature, then the internal consistency IS
  781. checked.
  782.  
  783.        Pre-2.0  versions  of  MSDOS did not check the signature byte for EXE
  784. files.
  785.  
  786. PC/MS-DOS Tips (2.0/2.1)                        18
  787.    ;This routine implements the UN*X system call (in spite of the fact that I
  788.    ;called it exec, the name in the DOS manual) under Lattice C although it
  789.    ;should be easy to adopt it to other languages.  One caution, it uses the
  790.    ;undocumented 037h DOS call to retrieve the switch character. This is
  791.    ; marked in the code and I will change it after DOS 2.0 so I'd rather
  792.    ;the DOS purists don't jump down my throat about this. If you don't like it
  793.    ;the way it is, change it.
  794.    ;
  795.    ;
  796.    ;                            Darrell Plank
  797.    ;                            BTL-IH
  798.         PAGE 55,132
  799.    ;
  800.    ; This function is modified from the macro by Brad Davis (b-davis@utah-cs)
  801.    ; The prolog and epilog are modified from Jim Holtman's macros for Pascal.
  802.    ;
  803.    ; exec( cmd)
  804.    ; char *md;
  805.    ;
  806.    ; This function accepts a string with the pathname of a command to be
  807.    ; executed and executes it.    The returned value is one of the following:
  808.    ;        0:       Successful
  809.    ;       -1:       Insufficient Memory
  810.    ;       -2:       Access Denied
  811.    ;       -3:       No such command
  812.    ;       -4:       Invalid command format
  813.    ;
  814.  
  815.    PROLOG  MACRO
  816.        PUSH    BP
  817.        MOV       BP,SP
  818.        ENDM
  819.  
  820.    EPILOG  MACRO   NUM
  821.        POP       BP
  822.        RET
  823.        ENDM
  824.  
  825. PC/MS-DOS Tips (2.0/2.1)                        19
  826.  
  827.    EXECVAL EQU       0
  828.    OVLVAL  EQU       3
  829.    FNCINT  EQU       21H
  830.    SETBLK  EQU       4AH
  831.    EXECF   EQU       4BH
  832.    CR       EQU       0DH
  833.  
  834.    PSP       STRUC
  835.    INTVECT DW       ?
  836.    TOM       DW       ?
  837.    RES1    DB       ?
  838.    DOSLONG DB       5 DUP (?)
  839.    TERMINA DD       ?
  840.    CTRLBRK DD       ?
  841.    CRITERR DD       ?
  842.    DOS1    DB       22 DUP (?)
  843.    ENVIRO  DW       ?
  844.    DOS2    DB       46 DUP (?)
  845.    FPA1    DB       16 DUP (?)
  846.    FPA2    DB       20 DUP (?)
  847.    UPA       DB       128 DUP (?)
  848.    PSP       ENDS
  849.  
  850.    EXECDEF STRUC
  851.    NENVIRO DW
  852.    COMMND  DW       2 DUP (0)
  853.    FCB5CH  DW       2 DUP (0)
  854.    FCB6CH  DW       2 DUP (0)
  855.    EXECDEF ENDS
  856.  
  857. PC/MS-DOS Tips (2.0/2.1)                        20
  858.  
  859.    PGROUP  GROUP PROG
  860.    PROG    SEGMENT BYTE PUBLIC 'prog'
  861.        ASSUME CS:PGROUP
  862.  
  863.    PUBLIC  EXEC
  864.    EXEC    PROC NEAR
  865.        PROLOG
  866.        PUSH    DS
  867.        PUSH    ES
  868.    ;
  869.    ; free up as much memory as we can
  870.    ;
  871.        MOV       AX,CS
  872.        PUSH    ES           ; Save ES for later
  873.        MOV       ES,AX
  874.        MOV       BX,SS
  875.        SUB       BX,AX
  876.        ADD       BX,1000H       ; 64K for stack segment
  877.        MOV       AH,SETBLK
  878.        INT       FNCINT
  879.        JNC       NEAR PTR LBL1
  880.        MOV       AX,-1       ; Insufficient memory
  881.        JMP       NEAR PTR FINE
  882.    LBL1:   POP       ES           ; Get ES's original value
  883.    ;
  884.    ; Save SS and SP registers
  885.    ;
  886.        MOV       CS:SPSAVE,SP
  887.        MOV       CS:SSSAVE,SS
  888.    ;
  889.    ; set up the parameter block
  890.    ;
  891.        MOV       CS:EXECBLK.NENVIRO,0    ; Inherit envir. from parent
  892.        MOV       AX,3700H           ; Undocumented call for SWITCHAR
  893.  
  894. PC/MS-DOS Tips (2.0/2.1)                        21
  895.  
  896.    ; W A R N I N G:  The following function call is undocumented and is
  897.    ; liable to disappear or change in future versions of DOS.
  898.        INT       FNCINT
  899.        MOV       CS:COMMAND[1],DL       ; Switchar
  900.        MOV       DX,4[BP]           ; Address of the command
  901.        MOV       SI,DX
  902.        MOV       DI,DX
  903.        CLD
  904.        XOR       AL,AL
  905.        MOV       CX,100H           ; Longest string can be 100h
  906.        REPNE SCASB               ; Find Null termination
  907.        SUB       DX,DI
  908.        NEG       DX
  909.        MOV       CX,DX
  910.        DEC       CX
  911.        ADD       DX,2
  912.        MOV       CS:COMMAND[0],DL       ; Save command length
  913.        LEA       DI,CS:COMMAND[4]
  914.        MOV       AX,CS
  915.        MOV       ES,AX
  916.        REP MOVSB               ; Copy command into our buffer
  917.        ASSUME  DS:PGROUP
  918.        MOV       AX,CS
  919.        MOV       DS,AX           ; DS points at code segment
  920.        MOV       BYTE PTR [DI],CR       ; Put in Carriage Return
  921.        LEA       DX,COMMAND
  922.        MOV       EXECBLK.COMMND[0],DX
  923.        MOV       EXECBLK.COMMND[2],DS
  924.        MOV       BX,OFFSET EXECBLK
  925.        XOR       SI,SI
  926.        MOV       DS,[SI].ENVIRO       ; Get environment address
  927.    ASSUME  DS:NOTHING
  928.        LEA       SI,CS:COMSPEC       ; Point SI at env. variable name
  929.        PUSH    DS               ; Swap
  930.        PUSH    ES               ; ES
  931.        POP       DS               ; and
  932.        POP       ES               ; DS
  933.        CALL    GETENV
  934.        PUSH    DS               ; Swap
  935.        PUSH    ES               ; them
  936.        POP       DS               ; back
  937.        POP       ES               ; again
  938.        MOV       AH,EXECF
  939.        MOV       AL,EXECVAL           ; OVLVAL here for overlay
  940.        INT       FNCINT
  941.        JC       NEAR PTR LBL2
  942.        MOV       AX,0            ; Successful exec
  943.        JMP       NEAR PTR FINE
  944.    LBL2:   MOV       SI,AX
  945.        MOV       AL,CS:ERRORS[SI]       ; Get error code
  946.        MOV       AH,0FFH           ; Sign extension - Assume Negative
  947.    FINE:   MOV       SS,CS:SSSAVE
  948.        MOV       SP,CS:SPSAVE
  949.        POP       ES
  950.        POP       DS
  951.        EPILOG  1
  952.  
  953. PC/MS-DOS Tips (2.0/2.1)                        22
  954.  
  955.    EXECBLK EXECDEF <>
  956.    ;
  957.    ; first byte of command s length excluding the length byte and the
  958.    ; trailing \r.  Second byte is switchar.
  959.    ;
  960.    COMMAND DB       2 DUP(?),"C ",254 DUP(?)
  961.    COMSPEC DB       "COMSPEC",0
  962.    SPSAVE  DW
  963.    SSSAVE  DW
  964.    ERRORS  DB       ?
  965.        DB       ?
  966.        DB       -3       ; No such command
  967.        DB       ?
  968.        DB       ?
  969.        DB       -2       ; Access denied
  970.        DB       ?
  971.        DB       ?
  972.        DB       -1       ; Insufficient memory
  973.        DB       ?
  974.        DB       ?
  975.        DB       -4       ; Invalid command format
  976.  
  977.    EXEC    ENDP
  978.  
  979.    ;
  980.    ; Getenv expects ES to have the environment paragraph and DS:SI to point
  981.    ; to an ASCIIZ string with the desired environment variable in it.
  982.    ; It returns the address of the proper string in ds:dx.
  983.    ;
  984.  
  985.        PUBLIC GETENV
  986.    GETENV  PROC NEAR
  987.  
  988.        PROLOG
  989.        PUSH    AX
  990.        PUSH    CX
  991.        PUSH    SI
  992.        PUSH    DI
  993.        MOV       CS:VARNAME,SI       ; Save offset of env. name
  994.        XOR       DI,DI
  995.  
  996. PC/MS-DOS Tips (2.0/2.1)                        23
  997.  
  998.    ;
  999.    ; At this point ds:si points to dummy variable environment name and
  1000.    ; es:di points to environment.
  1001.    ;
  1002.        CLD                   ;Forward string operations
  1003.    TOP:
  1004.        LODSB               ;Get a char. of env. name
  1005.        CMP       AL,0            ;If we're at the end
  1006.        JNE       NEAR PTR LBL3
  1007.        CMP       BYTE PTR ES:[DI],'='    ;Check for match
  1008.        JNE       NEAR PTR LBL4
  1009.    ;
  1010.    ; We matched
  1011.    ;
  1012.        INC       DI               ;Move beyond '='
  1013.        MOV       DX,DI
  1014.        POP       DI
  1015.        POP       SI
  1016.        POP       CX
  1017.        POP       AX
  1018.        EPILOG  2
  1019.    LBL4:
  1020.    ;
  1021.    ; At this point we found the end of the Env. variable name but it didn't
  1022.    ; match because the env. string was too long
  1023.    ;
  1024.        MOV       CX,-1
  1025.        REPNE SCASB               ;Find the end of the env. string
  1026.        CMP       BYTE PTR ES:[DI],0
  1027.        JNE       LBL3
  1028.        MOV       AX,-1           ;End of evironment area
  1029.        POP       DI
  1030.        POP       SI
  1031.        POP       CX
  1032.        POP       AX
  1033.        EPILOG  2
  1034. PC/MS-DOS Tips (2.0/2.1)                        24
  1035.  
  1036.    LBL3:
  1037.    ;
  1038.    ; Check if the next character matches
  1039.    ;
  1040.        AND       AX,11011111b        ;Capitalize the character in ax
  1041.        SCASB
  1042.        JE       TOP
  1043.    ;
  1044.    ; If we get here we don't have a match so move on
  1045.    ;
  1046.        MOV       SI,CS:VARNAME       ;Go back to start of env. string
  1047.        XOR       AX,AX
  1048.        MOV       CX,-1
  1049.        REPNE SCASB               ;Go to next env. variable
  1050.        CMP       BYTE PTR ES:[DI],0
  1051.        JNE       TOP
  1052.        MOV       AX,-1           ;End of environment area
  1053.        POP       DI
  1054.        POP       SI
  1055.        POP       CX
  1056.        POP       AX
  1057.        EPILOG  2
  1058.  
  1059.    VARNAME DW       ?
  1060.  
  1061.    GETENV  ENDP
  1062.  
  1063.    PROG    ENDS
  1064.        END
  1065. [This program will be kept in <INFO-IBMPC> as EXEC.ASM -ed]
  1066.  
  1067. PC/MS-DOS Tips (2.0/2.1)                        25
  1068. +----------------------------------------------------------------------------+
  1069. | D O S   2 . 1      I N T E R R U P T      2 1     F U N C T I O N   C O D E S |
  1070. +----------------------------------------------------------------------------+
  1071. +----+--------------------------+-----------------------+--------------------+
  1072. | AH |      F U N C T I O N    | Entry / Register Use    |     N O T E S   |
  1073. +----+--------------------------+-----------------------+--------------------+
  1074. | 00 | Program terminate    | CS=PSP seg. addr.    | Exit vectors are   |
  1075. |                                  restored         |
  1076. | 01 | Keyboard input        | N/A: returns AL    | waits for a char;  |
  1077. |                                  echoes it          |
  1078. | 02 | Display output        | puts DL        | break checked for  |
  1079. | 03 | AUX (Asynch) input    | N/A: returns AL    | Unbuffered,
  1080. |                                  non-interrupt      |
  1081. | 04 | AUX (Asynch) output    | puts DL        |     "        "     |
  1082. | 05 | Printer output        | puts DL        |             |
  1083. | 06 | Direct CON: I/O        | DL=FF input        | ZF set for no input|
  1084. | 07 | Direct CON: input Noecho | N/A: returns AL    |             |
  1085. | 08 | Console input     Noecho | N/A: returns AL    | Same as Fctn 1     |
  1086. |                              except no echo     |
  1087. | 09 | Print string        | DS:DX ==>string    | string terminator $|
  1088. | 0A | Buffered keyboard input    | DS:DX ==>buffer    | 1st byte is length |
  1089. | 0B | Check std. input status    | AL=FF if input    | AL=00 if no input  |
  1090. | 0C | Clear kybd buf. + other    | AL = function no.    | fctns 1,6,7,8,A    |
  1091. +----+--------------------------+-----------------------+--------------------+
  1092. | 0D | Disk reset        | N/A            | Flushes all buffers|
  1093. | 0E | Select disk        | DL=drive no.        | AL=no drives         |
  1094. |                            | on system         |
  1095. | 0F | Open file        | DS:DX ==> FCB     | AL=FF for error    |
  1096. | 10 | Close file        | DS:DX ==> FCB     | AL=FF for error    |
  1097. | 11 | Search for first entry    | DS:DX ==> FCB     | AL=FF for no match |
  1098. | 12 | Search for next entry    | DS:DX ==> FCB     | must follow fctn 11|
  1099. | 13 | Delete file        | DS:DX ==> FCB     | AL=FF for error    |
  1100. | 14 | Sequential read        | DS:DX ==> FCB     | EOF = 01 or 03     |
  1101. | 15 | Sequential write     | DS:DX ==> FCB     | AL=01 (full)         |
  1102. |                            |    02 (bad buffer) |
  1103. | 16 | Create file        | DS:DX ==> FCB     | AL=FF          |
  1104. |                              directory full     |
  1105. | 17 | Rename file        | DS:DX ==> FCB     | AL=FF for error    |
  1106. | 18 | Used internally by DOS:    |            |             |
  1107. | 19 | Current disk        | N/A: returns AL    |             |
  1108. | 1A | Set DTA            | DS:DX ==> new DTA    |             |
  1109. | 1B | Get FAT (default drive)    | N/A: returns DS:BX    | FAT id byte for    |
  1110. |                            | default drive      |
  1111. | 1C | Get FAT (select drive)    | N/A: returns DS:BX    | FAT id byte for DL |
  1112. | 1D | Used internally by DOS:    |            |             |
  1113. | 1E | Used internally by DOS:    |            |             |
  1114. | 1F | Used internally by DOS:    |            |             |
  1115. | 20 | Used internally by DOS:    |            |             |
  1116. | 21 | Random read        | DS:DX ==> FCB     | AL=00 good read    |
  1117. | 22 | Random write        | DS:DX ==> FCB     | AL=00 good write   |
  1118. | 23 | File size        | DS:DX ==> FCB     | AL=00 rrf=# records|
  1119. | 24 | Set random record field    | DS:DX ==> FCB     |             |
  1120. +----+--------------------------+-----------------------+--------------------+
  1121. | 25 | Set interrupt vector    | DS:DX = vector    | Int specified in AL|
  1122. | 26 | Create new PSP        | DX = segment no.    | Use 4B instead     |
  1123. +----+--------------------------+-----------------------+--------------------+
  1124. | 27 | Random block read    | DS:DX ==> FCB     | CX = record count  |
  1125. | 28 | Random block write    | DS:DX ==> FCB     | CX = record count  |
  1126. | 29 | Parse filename        | DS:SI ==> command    | AL = parse service |
  1127. +----+--------------------------+-----------------------+--------------------+
  1128. | 2A | Get date         | N/A: returns CX:DX    | CX=yr DH=mo DL=day |
  1129. | 2B | Set date         | CX:DX = new date    |             |
  1130. | 2C | Get time         | N/A: returns CX:DX    | CH=hr CL=min DH=sec|
  1131. | 2D | Set time         | CX:DX = new time    |             |
  1132. | 2E | Set / reset VERIFY    | DL=0, AL=1/0 (on/off    | See 54         |
  1133. +----+--------------------------+-----------------------+--------------------+
  1134. | 2F | Get DTA            | N/A: ES:BX ==>DTA    |             |
  1135.      |
  1136. | 30 | Get DOS version number    | N/A: returns AX    | AL=major AH=minor  |
  1137. | 31 | Stay res. terminate    | AL=retcode DX=size    |             |
  1138. | 32 | Used internally by DOS:    |            |             |
  1139. | 33 | Ctrl-Break check     | AL=00/01 (get/set)    |             |
  1140. |    |                | DL=00/01 (off/on)    |             |
  1141. | 34 | Used internally by DOS:    |            |             |
  1142. | 35 | Get interrupt vector    | N/A: returns ES:BX    | See 25         |
  1143. | 36 | Get disk free space    | DL=drive; returns BX    | DX=tot CX=bytes    |
  1144. |                            | AX=sectors         |
  1145. | 37 | Used internally by DOS:    | Get/set SWITCHAR    | AL=0/1 DL=char     |
  1146. | 38 | Get natl dependent info    | DS:DX ==> memory    | country dependent  |
  1147. +----+--------------------------+-----------------------+--------------------+
  1148. | 39 | MKDIR - Create subdir.    | DS:DX ==> ASCIIZ    | Errors 3,5         |
  1149. | 3A | RMDIR - Remove subdir.    | DS:DX ==> ASCIIZ    | Errors 3,5         |
  1150. | 3B | CHDIR - Change subdir.    | DS:DX ==> ASCIIZ    | Error  3         |
  1151. +----+--------------------------+-----------------------+--------------------+
  1152. | 3C | Create a file  (handle)    | DS:DX ==> ASCIIZ    | CX=attr BX handle  |
  1153. | 3D | Open a file    (handle)    | DS:DX ==> ASCIIZ    | AL=access code     |
  1154. | 3E | Close a file   (handle)    | BX = handle no.    | Error 6 only         |
  1155. | 3F | Read          (handle)    | BX = handle no.    | CX=read length     |
  1156. | 40 | Write          (handle)    | BX = handle no.    | CX=write length    |
  1157. | 41 | Unlink - Dir. delete    | DS:DX ==> ASCIIZ    | Errors 2,5ength    |
  1158. | 42 | LSEEK - Move r/w pointer | BX = handle no.    | AX = method         |
  1159. |                            | CX:DX = offset     |
  1160. | 43 | CHMOD - Change file mode | DS:DX ==> ASCIIZ    | AL=function         |
  1161. | 44 | IOCTL - I/O control    | BX = handle no.    | AL=function value  |
  1162. | 45 | DUP - Dup file handle    | BX = handle no.    | AX new handle      |
  1163. | 46 | FDUP - Force dup handle    | BX = handle no.    | CX second handle   |
  1164. +----+--------------------------+-----------------------+--------------------+
  1165. | 47 | Get current directory    | DL = drive        | DS:SI==>64byte area|
  1166. +----+--------------------------+-----------------------+--------------------+
  1167. | 48 | Allocate memory        | BX = no. para.    | AX block start     |
  1168. | 49 | Free memory        | ES ==> block        | Errors 7,9         |
  1169. | 4A | Modify allocated memory    | ES = block BX = size    | Errors 7,8,9         |
  1170. | 4B | EXEC - load a program    | DS:DX ==>ASCIIZ    | AL=function; 0 or 3|
  1171. +----+--------------------------+-----------------------+--------------------+
  1172. | 4C | EXIT - Terminate     | AL = retcode        | See FC 0         |
  1173. | 4D | WAIT - return code    | N/A: returns AX    |             |
  1174. | 4E | Find first match (ASCIIZ)| DS:DX ==> ASCIIZ    | CX = attrib         |
  1175. | 4F | Find next match    (ASCIIZ)| DTA ==> 4E call    | same as 4E         |
  1176. | 50 | Used internally by DOS:    |            |             |
  1177. | 51 | Used internally by DOS:    |            |             |
  1178. | 52 | Used internally by DOS:    |            |             |
  1179. | 53 | Used internally by DOS:    |            |             |
  1180. | 54 | Get VERIFY state     | N/A: AL=0/1 (on/off)    | See FC 2E         |
  1181. | 55 | Used internally by DOS:    |            |             |
  1182. | 56 | Rename a file    (ASCIIZ)| DS:DX ==> ASCIIZ    | same drive only    |
  1183. | 57 | Get/Set file date stamp    | BX = handle no.    | DX=date CX=time    |
  1184. |                    | AL = 0/1                     |
  1185. +----+--------------------------+-----------------------+--------------------+
  1186. | AH |      F U N C T I O N    | Entry / Register Use    |     N O T E S   |
  1187. +----+--------------------------+-----------------------+--------------------+
  1188.  
  1189. [70205,1217]
  1190. MASM.BUG       15-Apr-84 7975          10
  1191.  
  1192. Keywords: MASM ASSEMBLER PC-DOS BUGS
  1193.  
  1194.     This  document describes some problems, omissionas, bugs and limitations
  1195. in the IBM version of the Microsoft Macro Assembler.
  1196.  
  1197. Disposition:
  1198.  
  1199. <R D T): R
  1200.  
  1201.  
  1202.               The IBM / Microsoft Macro Assembler
  1203.                        -
  1204.                   Version 1.0
  1205.                        -
  1206.                 Known Problems
  1207.                        -
  1208.                       and
  1209.                        -
  1210.                   Usage Hints
  1211.                        -
  1212.  
  1213.                  John Chapman
  1214.  
  1215.                  [70205,1217]
  1216.  
  1217. Introduction
  1218.  
  1219.     This  document  describes several known limitations, bugs and quirks
  1220. of the IBM distributed Version (1.0) of the Microsoft Assembler.  Note  that
  1221. these descriptions are from various sources, and have been verified at least
  1222. once.   Some  of  these  problems are intermittent, dependent upon available
  1223. memory, program size, structure of source program, etc.
  1224.  
  1225.    Disclaimer
  1226.  
  1227.     Please  note that this document is provided without warrantee of any
  1228. kind.  Each individual must make the final determination of applicability to
  1229. a specific situation, program, or configuration.
  1230.  
  1231.    Audience
  1232.  
  1233.     This  document  is  intended  for the experienced assembler language
  1234. programmer.  The reader is assumed to be familiar with the 8086  instruction
  1235. set, the IBM Macro Assembler, and the IBM Personal Computer.
  1236.  
  1237.    Additions and Corrections
  1238.  
  1239.     This  document  will  be  periodically updated as new information is
  1240. made available.  If you have corrections, or additions, please send them to:
  1241.  
  1242.                John A. Chapman
  1243.                844 S. Madison St.
  1244.                Hinsdale, Illinois   60521
  1245.  
  1246.     Or: Send EMAIL to userid  [70205,1217] on Compuserv,
  1247.         or      MAIL to userid   $AC           on PCSHARE.
  1248.  
  1249. Assembler Tips                              2
  1250.  
  1251. Untrapped Errors
  1252.  
  1253.     When an instruction is accepted by the assembler, it is assumed that
  1254. the  instruction  is  not  only  syntactically  correct, but that it will be
  1255. decoded, as specified, into a legal machine operation.   In  MASM  1.0  this
  1256. does not always occur:
  1257.  
  1258. Segment Registers
  1259.  
  1260.     The  8088  does not support a compare with a segment register as the
  1261. register operand.  Coding
  1262.  
  1263.                CMP  ES,0
  1264. will generate the instruction
  1265.                CMP   AX,0    ....  without generating  a  diagnostic
  1266. message, or providing any other indication.
  1267.  
  1268. Omitted Operands
  1269.  
  1270.     Most   instructions   with  missing  operands  will  generate  error
  1271. messages; the instruction:
  1272.  
  1273.                MOV  AX,
  1274. produces
  1275.  
  1276.                MOV  AX,0 ... and no message
  1277.  
  1278.     Apparently, the above treatment occurs for all instructions that can
  1279. use  a  register  [non-segment  register]  with immediate data as the second
  1280. operand.  Zero is always used for the missing operand.
  1281.  
  1282. Missing Brackets
  1283.  
  1284.    Erroneous  code  will also be generated if square brackets are omitted in
  1285. certain operations, even thought an error message would be expected.
  1286.  
  1287.          MOV  BYTE PTR ES:DI,'$'      Is incorrect, and
  1288. generates:
  1289.          MOV  BYTE PTR ES:[7],'$'       Rather than what was intended,
  1290. which was:
  1291.          MOV  BYTE PTR ES:[DI],'$'
  1292.  
  1293.     This  appears to occur because the assembler finds DI in it's symbol
  1294. table, equated to it's register triplet '111'b, and substitutes the 7 as  if
  1295. the programmer had said DI equ 7.
  1296.  
  1297. Assembler Tips                              3
  1298.  
  1299. Data entry errors
  1300.  
  1301.     Always  scan comments in a newly entered program to assure that each
  1302. comment is preceded by a semi-colon [;],  rather  than  a  colon  [:].   The
  1303. assembler  will assume that the colon denotes a label, and will subsequently
  1304. generate the spurious message "OPEN PROCEDURES", and may generate additional
  1305. error messages.
  1306.  
  1307.     Review program labels in failing programs: the branch table sequence
  1308. below provides both correct and incorrect examples.
  1309.  
  1310.         Correct                  Incorrect
  1311.  
  1312.          JMP  CS:jumlist[BX]           JMP    CS:jumlist[BX]
  1313.          ...                     ...
  1314.          ...                     ...
  1315.     jumlist   DW  routin1            jumlist:  DW   routin1
  1316.           DW  routin2                  DW   routin2
  1317.  
  1318. Radix Specifications
  1319.  
  1320.     Even  if a RADIX pseudo-op has been used to specify the default base
  1321. for data values, the assembler will still check the  last  character  for  a
  1322. valid radix specification, and use it if present.  For example:
  1323.  
  1324.          SUB  BX,0B
  1325.  
  1326. generates:
  1327.          83 EB 00    .. which is incorrect for X'0B";
  1328. while:
  1329.          SUB  BX,11d   or    BX,0Bh      .. are both correct;
  1330.  
  1331. and will generate:
  1332.  
  1333.          83 EB 0B .... which is the intended instruction.
  1334.  
  1335. Pseudo-Operations
  1336.  
  1337.     The .XLIST pseudo operation will be ineffective [during both passes]
  1338. if the command line parameter /D is specified for the assembly.
  1339.  
  1340.     The  assembler will not correctly resolve 'identity' type definition
  1341. errors in the EQUATE pseudo-op.
  1342.  
  1343.     LOOP-IT   EQU  LOOP-IT           will cause the assembler to loop.
  1344.  
  1345. Assembler Tips                              4
  1346.  
  1347. Out of Memory Error in small programs
  1348.  
  1349. Occasionally  users  will  experience an MASM abort with the message "OUT OF
  1350. MEMORY", with a large amount of installed, available  memory,  and  a  small
  1351. program.  This problem is a recognized bug common to Pascal, MASM, and other
  1352. Microsoft products written in Pascal.
  1353.  
  1354.    A>ren masm.exe masm.xxx
  1355.    A>debug masm.xxx
  1356.    -s 0 ffff 81 fb 00 10 7e 03
  1357.    xxxx:FB23
  1358.    -d fb20,fb2f
  1359.    xxxx:FB20  00
  1360.    -e FB27
  1361.    xxxx FB27  7E.76    <===================Enter 76 in response to
  1362.                         first part of line
  1363.    -w
  1364.    WRITING 10800 BYTES
  1365.    -q
  1366.    A>
  1367.  
  1368.    The patch above corrects an invalid comparison for memory size, caused by
  1369. using JLE rather than JBE for the test.
  1370.  
  1371. Assembler Tips                              5
  1372.  
  1373. Reserved Words
  1374.  
  1375.    The  IBM/Microsoft assembler documentation does not provide documentation
  1376. on the reserved word list of the assembler.  This is especially unfortunate,
  1377. since the assembler will fail to provide a diagnostic message if a  reserved
  1378. word is used in place of an operand or label.
  1379.  
  1380. Example:
  1381.         MOV   ax,byte     ;BYTE not defined - no error reported
  1382.  
  1383. Pass 1 Errors omitted
  1384.  
  1385.    Errors caused in Pass 1 that are not repeated in pass 2 are not reported.
  1386.  
  1387. Example:
  1388.  
  1389.           IF1
  1390.                ABC     EQU  AX
  1391.           ENDIF
  1392.                        -- Incorrect equate - no error.
  1393.  
  1394. Macro Parameters
  1395.  
  1396.    If  a  macro is invoked within another macro, with a parameter which is a
  1397. quoted string constant, all