Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.csd.uwm.edu!cs.utexas.edu!uunet!cs.dal.ca!lane
From: lane@cs.dal.ca (John Wright/Dr. Pat Lane)
Newsgroups: comp.sys.ibm.pc
Subject: Patches to COMMAND.COM for DOS4.0x (LONG) *** CORRECTION ***
Summary: My old set of patches updated for several vers of DOS 4.0
Keywords: DOS COMMAND.COM patch environment size echo
Message-ID: <1989Aug18.174305.1071@cs.dal.ca>
Date: 18 Aug 89 17:43:05 GMT
Organization: Math, Stats & CS, Dalhousie University, Halifax, NS, Canada
Lines: 451

**** This is a corrected version of my posting of 14 Aug 89 04:56:38 GMT
**** (Message-ID: <1989Aug14.045638.26582@cs.dal.ca>).  In the original
**** posting, there were a couple of typos in the offsets for the ECHO-
**** space patch for MSDOS 4.00 and MSDOS 4.01 (arghh!).  Sorry to all
**** for any inconvenience and thanks to Roger L. Ferrel (ferrel@btni)
**** for pointing them out to me.


Some time ago I posted a set of patches for COMMAND.COM to do some nice
things like increase the default environment size and make ECHO OFF the
default for all batch files.  All these patches had been posted on Usenet
before but usually for a single version of DOS.  I presented the patches
for several DOS versions 3.10 to 3.30, from IBM, Microsoft and Compaq.
In this posting I present the patches for versions: IBM PCDOS 4.00,
Microsoft MSDOS 4.00 and Microsoft MSDOS 4.01.  In a companion posting
to this one, I present patches for IBM PCDOS 3.30, Microsoft MSDOS 3.30
and Compaq MSDOS 3.31.

In the companion posting, I explain that these latest versions of DOS
provide other means of accomplishing the same things as the patches.
With these methods, however, there remain limitations and inconveniences
which the patches can circumvent.


Users please note that these patches have been tested rather perfunctorily
and should be used with some caution.  Definitely keep an unpatched copy
of COMMAND.COM on a bootable disk.  If you mess up your regular copy of
COMMAND.COM, you won't be able to boot with it;  you'll have to boot from
the floppy and copy the original COMMAND.COM over the messed up one before
you can reboot normally.

Following the presentation of the patches for the various DOS versions,
I list a couple of batch files I use for effecting the patches.  Following
that I list the dis-assembled code around the patched areas so that those
with DOS versions other than those shown will be able to find the proper
offsets.

Remember to add 100h to offsets when patching with DEBUG.


OFFSETS for patch to COMMAND.COM for IBM PCDOS 4.00

Default environment size of 512 bytes
     [1B2A] = 0A 00 -> 20 00
ECHO OFF for AUTOEXEC.BAT
     [1FE3] = 03 -> 02
Echo off for batch files except AUTOEXEC.BAT
     [2D09] = 01 -> 00
ECHO produces blank line
     [543C-5452] -> [543E-5454] (everything moved down two bytes)
     [5439] = E8 9C 00 72 15 -> 51 E8 9B 00 59
     [543F] = 15 -> 16
     [5453] = 2C -> 2A
     [5455] = 00 74 -> 90 E3
     [548B] = C4 -> C6
     [54CC] = 83 -> 85

The echo-space patch is quite involved and completely different from
previous versions. See below for details.


OFFSETS for patch to COMMAND.COM for Microsoft MSDOS 4.00

Default environment size of 512 bytes
     [1B2A] = 0A 00 -> 20 00
ECHO OFF for AUTOEXEC.BAT
     [1FE3] = 03 -> 02
Echo off for batch files except AUTOEXEC.BAT
     [2CCE] = 01 -> 00
ECHO produces blank line
     [540B-5421] -> [540D-5423] (everything moved down two bytes)
     [5408] = E8 9C 00 72 15 -> 51 E8 9B 00 59
     [540E] = 15 -> 16
     [5422] = 2C -> 2A
     [5424] = 00 74 -> 90 E3
     [545A] = C4 -> C6
     [549B] = 83 -> 85



OFFSETS for patch to COMMAND.COM for Microsoft MSDOS 4.01

Default environment size of 512 bytes
     [1B2A] = 0A 00 -> 20 00
ECHO OFF for AUTOEXEC.BAT
     [1FE3] = 03 -> 02
Echo off for batch files except AUTOEXEC.BAT
     [2CCE] = 01 -> 00
ECHO produces blank line
     [540C-5422] -> [540E-5424] (everything moved down two bytes)
     [5409] = E8 9C 00 72 15 -> 51 E8 9B 00 59
     [540F] = 15 -> 16
     [5423] = 2C -> 2A
     [5425] = 00 74 -> 90 E3
     [545B] = C4 -> C6
     [549C] = 83 -> 85



Following are two batch files PATCH.BAT and UNPATCH.BAT for installing and
un-installing the patches for IBM PC-DOS 4.00.  It should be easy enough
to modify this for other DOS 4 versions.

----------------- PATCH.BAT for IBM PCDOS 4.00 --------------------
echo off
echo INSTALL COMMAND.COM PATCHS FOR IBM PC-DOS 4.00
rem usage PATCH [filespec]
rem Patch 1. Default environment size is 512 bytes
rem Patch 2. ECHO OFF default for AUTOEXEC.BAT
rem Patch 3. ECHO OFF default for batch files except AUTOEXEC.BAT
rem Patch 4. ECHO-space produces blank line
if "%1"=="" goto :default
set $s=%1
echo About to modify %$s%
goto pause
:default
set $s=COMMAND.COM
echo About to modify %$s% in the default drive and directory
:pause
pause
if not exist %$s% goto error
echo Creating PATCH.TMP...
echo e1C2A >>patch.tmp
echo 20 00 >>patch.tmp
echo e20E3 >>patch.tmp
echo 02 >>patch.tmp
echo e2E09 >>patch.tmp
echo 00 >>patch.tmp
echo m553C,5552,553E >>patch.tmp
echo e5539 >>patch.tmp
echo 51 E8 9B 00 59 >>patch.tmp
echo e553F >>patch.tmp
echo 16 >>patch.tmp
echo e5553 >>patch.tmp
rem note *two* spaces bewtten 2A and 90 below
echo 2A  90 E3 >>patch.tmp
echo e558B >>patch.tmp
echo C6 >>patch.tmp
echo e55CC >>patch.tmp
echo 85 >>patch.tmp
echo w >>patch.tmp
echo q >>patch.tmp
debug %$s% patch.tmp
echo 0A 00 >>patch.tmp
echo e20E3 >>patch.tmp
echo 03 >>patch.tmp
echo e2E09 >>patch.tmp
echo 01 >>patch.tmp
echo m553E,5554,553C >>patch.tmp
echo e5539 >>patch.tmp
echo E8 9C 00 >>patch.tmp
echo e553D >>patch.tmp
echo 15 >>patch.tmp
echo e5551 >>patch.tmp
rem note *two* spaces between 2C and 80 below
echo 2C  80 F9 00 74 >>patch.tmp
echo e558B >>patch.tmp
echo C4 >>patch.tmp
echo e55CC >>patch.tmp
echo 83 >>patch.tmp
echo w >>patch.tmp
echo q >>patch.tmp
debug %$s% >
3576:1C2C BA746D        MOV   DX,6D74
3576:1C2F B104          MOV   CL,04
3576:1C31 D3EA          SHR   DX,CL
3576:1C33 89169F24      MOV   [249F],DX

Just searching for '0A 00' should find this one.


Echo off for AUTOEXEC.BAT

-u 20dc l27
3576:20DC A1DA0E        MOV   AX,[0EDA]
3576:20DF C606300F03    MOV   BYTE PTR [0F30],03       <>
3576:20EC 33FF          XOR   DI,DI
3576:20EE B000          MOV   AL,00
3576:20F0 AA            STOSB
3576:20F1 B001          MOV   AL,01
3576:20F3 AA            STOSB
3576:20F4 33C0          XOR   AX,AX
3576:20F6 AB            STOSW
3576:20F7 AB            STOSW
3576:20F8 AA            STOSB
3576:20F9 AB            STOSW
3576:20FA AB            STOSW
3576:20FB B8FFFF        MOV   AX,FFFF
3576:20FE B90A00        MOV   CX,000A
3576:2101 F3            REPZ
3576:2102 AB            STOSW

Searching for '03 C7 06' works in ver 3.30 and above.  Searching for
'8E C0 33 FF B0 00' worked in 3.20 and above.  All those STOSW/B's should
stand out pretty well.


Echo off for other batch files

-u 2df6
3576:2DF6 26            ES:
3576:2DF7 803E420F01    CMP   BYTE PTR [0F42],01
3576:2DFC 7403          JZ    2E01
3576:2DFE E80708        CALL  3608
3576:2E01 E8A420        CALL  4EA8
3576:2E04 26            ES:
3576:2E05 A0300F        MOV   AL,[0F30]
3576:2E08 2401          AND   AL,01               <>
3576:2E0D 26            ES:
3576:2E0E F706DA0EFFFF  TEST  WORD PTR [0EDA],FFFF
3576:2E14 7414          JZ    2E2A

Look for '24 01 50 33 C0'.



Echo-blank produces blank line

For DOS 4.00, they made some significant changes to the code that processes
the ECHO command.  It now uses code in common with BREAK and VERIFY and
this makes the patch for this area much more complicated.  I worked some-
thing out which appears to work but I'm still a bit uncomfortable with
it and I'm not sure there isn't a better way.  As such, I present all
the code involved and explain the fix in some detail.  If you see a
problem or a better way, do let me know.

ECHO followed by only blanks and tabs, would normally be interpreted as
ECHO without arguments and result in the "ECHO is on|off" message (just
like BREAK and VERIFY).  ECHO followed by a single arg, "on" or "off",
causes a flag to be set or unset (again, same thing for BREAK and VERIFY).
ECHO followed by any other text causes the text to be output to stdout
(unlike BREAK and VERIFY where an arg. besides "on" or "off" is an error)

The code sections that process ECHO, BREAK and VERIFY all call a routine
that sets flags and registers to indicate whether there are command line
arguments and whether there is only a single "on" or "off".  As in previous
DOS versions, all three code sections are entered with the contents of
[CS:0080], the length of the command line following the command keyword,
in CL.  Unlike previous DOS versions, the routine that checks arguments
changes CX (returning it zero if there are no arguments).

What we want to do here is to print the command line argument buffer even
when it contains only blanks and tabs.  In this case, the argument checking
routine will indicate no arguments but [CS:0080] will be non-zero.  My
solution was to put CX on the stack before calling the routine, restore it
after and test the original CX instead of the value returned in CX.  In
order to save some bytes I had to change CMP CL,0, JZ xxxx to JCXZ xxxx.
To insert the PUSH and POP instructions for preserving CX, I had to move
a section of code down two bytes and change a couple of jumps that pointed
into this code.  Pretty hairy!


                        <>
                        <>

3576:5539 E89C00        CALL  55D8      <>
3576:553C 7215          JB    5553      <>
3576:553E 8E1E1C62      MOV   DS,[621C]
3576:5542 7506          JNZ   554A
3576:5544 800E300F01    OR    BYTE PTR [0F30],01  <>
3576:5549 C3            RET
3576:554A 8026300FFE    AND   BYTE PTR [0F30],FE  <>
3576:554F C3            RET

                        <>

3576:5550 E92CF3        JMP   487F

                        <>

3576:5553 80F900        CMP   CL,00          <>
3576:5556 7409          JZ    5561           <>
3576:5558 BA8200        MOV   DX,0082        <>
3576:555B E826F0        CALL  4584
3576:555E E9C6EF        JMP   4527           <>

                        <>

3576:5561 8E1E1C62      MOV   DS,[621C]      <>
3576:5565 8A1E300F      MOV   BL,[0F30]
3576:5569 0E            PUSH  CS
3576:556A 1F            POP   DS
3576:556B 80E301        AND   BL,01
3576:556E BA3C5A        MOV   DX,5A3C
3576:5571 EB22          JMP   5595           <>

                        <>

3576:5573 E86200        CALL  55D8
                        ...
3576:558A 75C4          JNZ   5550           <>
                        ...

                        <>

3576:5595 BE4D5A        MOV   SI,5A4D
                        ...
3572:55B5 C3            RET

                        <>

3576:55B6 E81F00        CALL  55D8
                        ...
3576:55CB 7583          JNZ   5550           <>
                        ...
3572:55D6 EBBD          JMP   5595

                        <>

3576:55D8 BE8100        MOV   SI,0081        <>
                        ...
3576:562C C3            RET

This routine is somewhat involved and I've left out details.  It returns
flags and registers as follows:
    echo on    CF=0 ZF=1 AX=-1     CX=1 BX=2E20   DX=0
    echo off   CF=0 ZF=0 AX=-1     CX=1 BX=2E20   DX=0
    echo text  CF=1 ZF=0 AX= 8     CX=8 BX=2E20   DX=59FD
    echo       CF=1 ZF=1 AX=-1     CX=0 BX=2EB9   DX=59FD
Thus if CF is unset, we had an "on" or "off" (indicated by ZF flag), if
CF is set, we had other text (in which case AX=8) or no args (AX=-1);
As well, CX=1 for "on"/"off", CX=8 for other text or CX=0 for no args.



The patched code is as follows:

3572:5539 51            PUSH  CX                 <- inserted
3572:553A E89B00        CALL  55D8               <- moved & offset changed

3572:553D 59            POP   CX                 <- inserted
3572:553E 7216          JB    5556               <- moved & offset changed
3572:5540 8E1E1C62      MOV   DS,[621C]            \
3572:5544 7506          JNZ   554C                  | moved
3572:5546 800E300F01    OR    BYTE PTR [0F30],01    | down
3572:554B C3            RET                         | two
3572:554C 8026300FFE    AND   BYTE PTR [0F30],FE    | bytes
3572:5551 C3            RET                        /
3572:5552 E92AF3        JMP   487F               <- moved & offset changed
3572:5555 90            NOP                      <- changed
3572:5556 E309          JCXZ  5561               <- changed
3572:5558 BA8200        MOV   DX,0082
3572:555B E826F0        CALL  4584
3572:555E E9C6EF        JMP   4527
               ...
3572:558A 75C6          JNZ   5552               <- offset changed
               ...
3572:55CB 7585          JNZ   5552               <- offset changed


Good luck and let me know if you have problems with these patches.

-- 
John Wright      //////////////////     Phone:  902-424-3805  or  902-424-6527
Post: c/o Dr Pat Lane, Biology Dept, Dalhousie U, Halifax N.S., CANADA B3H-4H8 
Cdn/Eannet:lane@cs.dal.cdn  Uucp:lane@dalcs.uucp or {uunet watmath}!dalcs!lane
Arpa:lane%dalcs.uucp@uunet.uu.net  Internet:lane@cs.dal.ca