[comp.sys.ibm.pc.misc] Command.com patches

mikep@hydra.unm.edu (Mike Prine CIRT) (12/27/90)

I have seen several request on the net for changing the default environment
space and echo processing so thought I'd pass along a copy of an article I
recieved over a year ago.

Note: Although I have checked the code for typos don't assume I caught them all.
      For most users deleting everything except the 1st patch is probably best
      but proceed with caution in any case and make sure you have backups and a
      bootable floppy before trying any of this. At the end I have included info
      on the offsets of the various patches for several versions of DOS we had.
      I will also be posting the companion posting John mentions as soon as I
      can get it scanned in.
      (Mike Prine@ the University of New Mexico in Albuquerque)

If John Wright, the original author, is still around maybe he could make this
or a more current vesion avaliable for FTP from one of the common sites for
such things.

Article 36808 of comp.sys.ibm.pc:
Path; ariel!~nmv~x!tut.c~s.ohlo-state.edu!clca!ctr~ol!3inosko!uunet!cs.dal.cal1a
>From: lane@cs.dal.ca (John Wright/Dr. Pat Lane)
Newsgroups: comp.sys.ibm.pc
Subject: Patches to COMMAND.COM for DOS4.0x (Long)
Summary: My old set of Patches updated for several vers of DOS 4.0
Keywords: DOS COMMAND.COM patch environment size echo
Message-ID <1988Aug14.045638.26582@cs.dal.ca>
Date: 14 Aug 89 04:56:38 GMT
Organization: Math, Stats & CS, Dalhousie University, Halifax. NS, Canada
Lines; 449


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 version 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, Mlcrosoft MSDOS 3.30
and Compaq MSDOS 3.31.

ln 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 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<space> 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 compleatly 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<space> 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
     [546A] = C4 -> C6
     [549B] = 83 -> 85



OFFSETS for patch to COMMAND.COM for Microsoft MSDOS 4.01

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



Following are two batch files PATCH.BAT and UNPATCH.BAT for installing and
un-installlng 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 PATCHES FOR IBM PC-DOS 4.0
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=%l
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
it not exist %$s% goto error
echo Creating PATCH.TMP...
echo e1C2A >patch.tmp
echo 20 00 >>patch.tmp
rem end of patch 1
echo e20E3 >>patch.tmp
echo 02 >>patch.tmp
rem end of patch 2
echo e2E09 >>patch.tmp
echo 00 >>patch.tmp
rem end of patch 3
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 between 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
rem end of patch 4
echo w >>patch.tmp
echo q >>patch.tmp
debug %$s% <patch.tmp
echo Deleting PATCH.TMP
del patch.tmp
echo Modification complete.  Reboot system . . .
pause
goto exit
:error
echo %$s% not found
:exit
---------------- END OF PATCH.BAT -----------------------------
------------------- UNPATCH.BAT for IBM PCDOS 4.00 -------------------
echo off
echo UNINSTALL COMMAND.COM PATCHES FOR IBM PC-DOS 4.00
rem usage UNPATCH [filespec]
rem Patch 1. Default environment size is 160 bytes
rem Patch 2. ECHO ON default for AUTOEXEC.BAT
rem Patcn 3. ECHO ON default for batch files except AUTOEXEC.BAT
rem Patch 4. ECHO<space> produces  ECHO is on|off
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 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 2A 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% <patch.tmc
echo Deleting PATCH.TMP
del patch.tmp
echo Modification complete.  Reboot system . . .
pause
goto exit
:error
echo %$s% not found
:exit
---------------------------- END OF UNPATCH.BAT --------------------------


Below, I present sections of code from IBM PCDOS 4.00, dis-assembled with
DEBUG so that those with versions of DOS other than the ones listed above
can find the offsets for their COMMAND.COM.

As you probably know, various OEM's (IBM, Compaq, AT&T, Tandy, Olivetti,
Toshiba, etc.) all license MS-DOS from Microsoft. (I've heard something
to the effect that IBM did the development work on DOS 4.0 and sold it
back to Microsoft, but I'm not sure about that). Anyway, the OEMs are
free to make their own modifications, supposedly to tailor the system to
their hardware so, there are a multitude of MS/PC-DOS versions, all slightly
different at the code level. Since they get the source, modify it, and re-
compile, the smallest change can result in a completely different binary.

In every most DOS versions, most of the sections of code to be patched
are unchanged, they're simply shifted in position so it's just a question
of locating the correct offset, by searchlng for strings of bytes from the
sections, of code listed below. The main trick here is to avoid addresses
in the code which are likely to be different (most absolute addresses will
be different while relative addresses may not be different). Assuming
you're handy with DEBUG or a similar debugger and know some 8088 assembly,
you should be able to pull it off. If DEBUG's search command is too limited,
you might try Unassembling the whole COMMAND.COM to a text file and using
an editor or lister utility to search.


Here are the sections of code from IBM PCDOS 4.00:

First, a minor formality,

d 13f0 l60
2320:13F0  49 42 4D 20 44 4F 53 20-56 65 72 73 69 6F 6E 20   IBM DOS Version
2320:1400  34 2E 30 30 20 28 43 29-43 6F 70 79 72 69 67 68   4.00 (C)Copyrigh
2320:1410  74 20 49 42 4D 20 43 6F-72 70 20 31 39 38 31 2C   t IBM Corp 1981,
2320:1420  31 39 38 38 4C 69 63 65-6E 73 65 64 20 4D 61 74   1988Licensed Mat
2320:1430  65 72 69 61 6C 20 2D 20-50 72 6F 67 72 61 6D 20   erial - Program
2320:1440  50 72 6F 70 65 72 74 79-20 6F 66 20 49 42 4D FF   Property of IBM.

The environment size

-u 1c0e l29
2320:1C0E A10200        MOV     AX,[0002]
2320:1C11 8C1E6E10      MOV     [106E],DS
2320:1C15 8C1E7210      MOV     [1072],DS
2320:1C19 8C1E6610      MOV     [1066],DS
2320:1C1D A3260F        MOV     [0F26],AX
2320:1C20 C70691245400  MOV     WORD PTR [2491],0054
2320:1C26 C7068F240A00  MOV     WORD PTR [248F],000A    <<default envir. size>>
2320:1C2C BA746D        MOV     DX,6D74
2320:1C2F B104          MOV     CL,04
2320:1C31 D3EA          SHR     DX,CL
2320:1C33 89169F24      MOV     [249F],DX

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


Echo off for AUTOEXEC.BAT

-u 20dc l27
2320:20DC A1DA0E        MOV     AX,[0EDA]
2320:20DF C606300F03    MOV     BYTE PTR [0F30],03    <<Change 03 to 02 for
2320:20E4 C7063F0F0100  MOV     WORD PTR [0F3F],0001    ECHO OFF in AUTO-
2320:20EA 8EC0          MOV     ES,AX                   EXEC,BAT>>
2320:20EC 33FF          XOR     DI,DI
2320:20EE B000          MOV     AL,00
2320:20F0 AA            STOSB
2320:20F1 B001          MOV     AL,01
2320:20F3 AA            STOSB
2320:20F4 33C0          XOR     AX,AX
2320:20F6 AB            STOSW
2320:20F7 AB            STOSW
2320:20F8 AA            STOSB
2320:20F9 AB            STOSW
2320:20FA AB            STOSW
2320:20FB B8FFFF        MOV     AX,FFFF
2320:20FE B90A00        MOV     CX,000A
2320:2101 F3            REPZ
2320: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
2320:2DF6 26            ES:
2320:2DF7 803E420F01    CMP     BYTE PTR [0F42],01
2320:2DFC 7403          JZ      2E01
2320:2DFE E80708        CALL    3608
2320:2E01 E8A420        CALL    4EA8
2320:2E04 26            ES:
2320:2E05 A0300F        MOV     AL,[0F30]
2320:2E08 2401          AND     AL,01               <<change 01 to 00 for
2320:2E0A 50            PUSH    AX                    ECHO OFF in regular
2320:2E0B 33C0          XOR     AX,AX                 batch files>>
2320:2E0D 26            ES:
2320:2E0E F706DA0EFFFF  TEST    WORD PTR [0EDA],FFFF
2320: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 nornally be interpreted as
ECHO without arguments and resutt ln 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 BEARK 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 sectlons 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
solutlon 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 sectlon of code down two bytes and change a couple of jumps that pointed
into this code.  Pretty hairy!


                        <<ECHO processing>>
                        <<at this point arg string length is in CX>>

2B14:5539 E89C00        CALL    55D8    <<call subr. to check args>>
2B14:553C 7215          JB      5553    <<jump if not ON or OFF>>
2B14:553E 8E1E1C62      MOV     DS,[621C]
2B14:5542 7506          JNZ     554A
2B14:5544 800E300F01    OR      BYTE PTR [0F30],01  <<set echo flag on>>
2B14:5549 C3            RET
2B14:554A 8026300FFE    AND     BYTE PTR [0F30],FE  <<set echo flag off>>
2B14:554F C3            RET

                        <<this is to take a short jump to a near (not short)
                          addr,; it is used by two jump-if instr. later on>>

2B14:5550 E92CF3        JMP     487F

                        <<ECHO w/o args or args other than "on/off">>

2B14:5553 80F900        CMP     CL,00        <<test CL from arg. routine>>
2B14:5556 7409          JZ      5561         <<jump if no args>>
2B14:5558 BA8200        MOV     DX,0082      <<display text up to CR>>
2B14:555B E826F0        CALL    4584
2B14:555E E9C6EF        JMP     4527         <<jump to output newline & RET>>

                        <<ECHO w/o args>>

2B14:5561 8E1E1C62      MOV     DS,[621C]    <<check echo flag>>
2B14:5565 8A1E300F      MOV     BL,[0F30]
2B14:5569 0E            PUSH    CS
2B14:556A 1F            POP     DS
2B14:556B 80E301        AND     BL,01
2B14:556E BA3C5A        MOV     DX,5A3C
2B14:5571 EB22          JMP     5595         <<jump to common code to
                                               display "ECHO is on/off">>

                        <<BREAK processing>>

2B14:5573 E86200        CALL    55D8
                        ...
2B14:558A 75C4          JNZ     5550         <<if "BREAK test", an error>>
                        ...

                        <<common code for ECHO,BREAK display "xxxx is on/off">>

2B14:5595 BE4D5A        MOV     SI,5A4D
                        ...
2B14:55B5 C3            RET

                        <<VERIFY processing>>

2B14:55B6 E81F00        CALL    55D8
                        ...
2B14:55CB 7583          JNZ     5550          <<if "VERIFY text", an error>>
                        ...
2B14:55D6 EBBD          JMP     5595

                        <<proc. args for ECHO, BREAK and VERIFY>>

2B14:55D8 BE8100        MOV     SI,0081       <<argument buffer>>
                        ...
2B14: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 CX=8) or no args (AX=-1);
As well, CX=1 for "on"/"off", CX=8 for other text or CX=0 for no arqs.



The patched code is as follows:

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

2B14:553D 59            POP     CX          <- inserted
2B14:553E 7216          JB      5556        <- moved & offset changed
2B14:5540 8E1E1C62      MOV     DS,[621C]          \
2B14:5544 7506          JNZ     554C                | moved
2B14:5546 800E300F01    OR      BYTE PTR [0F30],01  | down
2B14:554B C3            RET                         | two
2B14:554C 8026300FFE    AND     BYTE PTR [0F30],FE  | bytes
2B14:5551 C3            RET                        /
2B14:5552 E92AF3        JMP     487F        <- moved & offset changed
2B14:5555 90            NOP                 <- changed
2B14:5556 E309          JCXZ    5561        <- changed
2B14:5558 BA8200        MOV     DX,0082
2B14:555B E826F0        CALL    4584
2B14:555E E9C6EF        JMP     4527
                        ...
2B14:558A 75C6          JNZ     5552        <- offset changed
                        ...
2B14: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, Hlalifax N.S., CANADA B3H-4H8
Cdn/Eannet:lane@cs.dal.cdn Uucp:lane@dalcs.uucp or {uunet watmath}!dalcsllane
Arpa;lane~dalc,.uucp~uunet.uu.net  Internet:lane~c,.dal.c~
--
John Wright ////////////           Phone: 902-424-3~05 or 902--424-6527

========================================================================
========================================================================
Offset information for some other DOS versions
========================================================================
========================================================================

Version         Environment     Echo-1      Echo-2      Echo-3
                                                           
MSDOS 3.10      0DE1            112B        19C7        38E8
MSDOS 3.20      0E2F            123E        1BAC        3B48
MSDOS 3.21      0E2F            123E        1BBC        3B58
PCDOS 3.30      0EB8            1304        1D68        3F29
MSDOS 3.30+     0EB8            1304        1DF7        3FF9
Telex 3.30      0EB8            1304        1DF7        3F49
Telex 3.21      0D4F            115E        1ABC        3A18

Enjoy.
~                                                                               
~                                                                               

~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~                                                                               
~