|11: EDBIN - The binary editor|
EDBIN is the name of the transient utility which provides the facility for EDiting of BINary files in DOS. Binary files are defined as any file which does not contain exclusively displayable alphanumeric characters in the range 20h to 7Eh.
By using EDBIN, any file can be loaded into memory and examined, amended and resaved as necessary. Commands are provided for loading a file into memory, editing memory in hexadecimal and ASCII, for initialising areas of memory to a specified byte or word value, for copying the contents of a block of memory to a different location, for searching for a specified string and comparing two areas of memory.
After editing, data can be written back to disc, either to an original filename or as a different name if required. All EDBIN commands can be terminated at any time by using CTRL-C, or suspended using CTRL-S. If console output is suspended by using CTRL-S, it can be restarted using any key except CTRL-C, CTRL-S or BREAK. The EDBIN program is included on the DOS Plus Boot Disc (Issue Disc 1).
Two methods are permitted when first calling EDBIN. It may be called either with a filename as a command tail, or with no command tail. This permits a filename to be supplied immediately if, perhaps, only one file is to be edited; or for several files to be loaded and saved from within EDBIN. Filenames may include a drive and path specification.
To load EDBIN with a filename supplied, at the DOS prompt enter:
where <filename> is the file that you wish to edit. The file will be loaded into memory by EDBIN automatically, which will then output a '-' prompt to indicate that it is ready to accept further commands.
Alternatively, if you wish to change discs after loading EDBIN because the file is on a different disc, EDBIN can be started by entering only its name. Again, EDBIN is loaded and responds with the prompt, but no file is loaded for editing. In this mode memory can be examined and modified without loading a file, or files may be loaded, edited and resaved.
All EDBIN commands are entered as a single letter, followed by between zero and five parameters terminated by a RETURN. The simplest command is the help command, which requires only an H with no parameters. The redirected console output, produced by entering EDBIN, issuing the help command and quitting, is shown below for illustration:
Filename not specified
EDBIN Version 0.52
Avai1able commands are:
c(ompare) (<segment>:) <source start> <source end> (<segment>:) <dest start>
d(ump) (<segment>:) (<start offset>) (<end offset>)
e(dit) (<segment>:) <offset>
f(ill) (<segment>:) (<start offset>) (<end offset>) <end offset> <fill byte|word>
m(ove) (<segment>:) <source start> <source end> (<segment>:) <dest start>
s(earch) (<segment>:) (<start offset>) (<end offset>}) <"string">
The command prefix is entered immediately following the prompt and identifies the function to be carried out using, where appropriate, the parameters which follow.
Items in angled brackets, eg <segment>, indicate required parameters though, in some cases, these may be defaulted. Items in round brackets, eg (<segment>), indicate that the enclosed item is optional and may be omitted from the command. If it is, as in the case of (<segment>), and as the enclosed item is a required parameter, a suitable default value will be supplied by EDBIN.
Items separated by a vertical bar, eg <fill byte | word>, are mutually exclusive alternative entries. One and only one of the two must be supplied. EDBIN commands conform to normal DOS syntax and commands are not case sensitive, with the exception of the <"string"> argument in the (S)earch command.
Where a segment address must be supplied, leading zeros can be omitted and any address (stated in paragraphs) may be specified, but wherever a segment address is supplied, it must be immediately succeeded by a colon. If no segment address is supplied the colon is also omitted.
For all commands, if the segment address is omitted, the most recently specified (ie current) segment is used by default. If the segment is omitted and no segment has been specified in a previous command, the value will default to the address of the current file buffer. Unnecessary leading or trailing spaces are ignored.
Where an offset is required, it may similarly be entered as one to four digits without leading zeros, for example, 50h can be entered as 50, 050 or 0050. If more than 4 hex digits are entered, the most significant digits are ignored, for example, 12345 would be treated as 2345 where <end offset> is required, it refers to the byte after the last one required. For example:
D 100 180
will dump the bytes between 100h and 17Fh inclusive. To specify the end address of a 64k segment in 16 bits, an end offset of 0 is used (ie 0FFFFh + 1), so that:
F C000 0 E5
would fill the last 4k bytes of the current segment with the byte value E5h.
The following table further expands on the meaning of the commands given in the help display above.
|C(ompare)||memory, byte by byte, in the specified segment from the specified start offset up to the specified end offset, with the target segment:offset, reporting differences.
|D(ump)||memory contents to the console output device in hex and ASCII formats, starting in the specified segment at the start offset up to the end offset.
|E(dit)||memory from the specified segment:offset in hex and/or ASCII values.
|F(ill)||memory starting from the specified segment:offset with the supplied constant byte or word value.
|H(elp)||gives a summary of commands and syntax as shown above.
|M(ove)||a block of memory starting at the specified segment:offset, ending at the specified end offset, to the memory beginning at the specified destination segment:offset.
|Q(uit)||EDBIN and return to the calling environment.
|R(ead)||a file into memory for editing.
|S(earch)||memory, starting at the specified segment:offset, continuing to the specified end offset, for matches of the specified string.
|W(rite)||memory to the specified disc filename.|
|Table 11.1 EDBIN Command Functions.|
The operation of EDBIN is very similar to that of the 80186 monitor; therefore, where commands are similar this is pointed out. For such commands more comprehensive illustrations are available in the monitor examples (see Chapter Three).
A more detailed explanation of EDBIN commands follows below.
C (<seg>:) <src start> <src end> (<seg>:) <dest start>
Compares the block of memory, byte by byte, between the offsets source start and source end in the start segment, with the same sized block of memory beginning at <dest start> in the second segment specified.
C attempts to match the two specified memory areas and, if differences are found, reports them in the form:
<source address> <source byte> <dest address> <dest byte>
The addresses are displayed in standard segment:offset format and the byte content at that address is displayed in both hexadecimal and ASCII.
If there are no differences between the two blocks of memory EDBIN displays nothing, returning only the '-' prompt to indicate that the blocks are identical.
Compare can be used on single memory blocks of up to a segment in length by specifying an end offset of 0 for the source end address. If a comparison of greater than 64k bytes is required, it must be divided into blocks of 64 kilobytes and several commands must be used.
C 4000:0 1000 5000:0
compares the first 1000h bytes of segment 4000h with the same area in segment 5000h.
C 300 500 1000
compares the 200h bytes starting at 300h and extending to 4FFh in the current (defaulted) segment, with 200h bytes starting at 1000h, also in the current segment.
C 0 0 2000:0
compares the whole 64 kilobytes of the current segment with another 64k block starting at segment 2000h.
D (<segment>:) (<start offset>) (<end offset>)
This command is identical to the monitor's dump command and produces a memory dump of the 512's RAM to the console output device between the specified addresses. The display is in hex and ASCII, showing 16 bytes on each line. The start address of each line is shown in the normal segment:offset format. Characters outside the standard ASCII range of 20h to 7Eh (CHR$32 to CHR$127) are shown as a full stop in the ASCII portion of the display.
All parameters in this command are optional and may be defaulted. If the segment address is omitted, the last used segment value (or the default buffer address) is used. If the start offset is omitted the display begins from the address of the last byte displayed plus one, or zero if there is no previous address. If the end address is omitted, the start address pIus 128 bytes are displayed. As displays are in multiples of 16 bytes, the default display length is 144 bytes. It impossible to specify an end offset without also supplying a start offset.
The memory contents are displayed as hexadecimal values and ASCII characters. Each line of the memory dump shows the memory address in segment:offset form, followed by 16 bytes of memory contents in hexadecimal values and ASCII characters. Characters outside the ASCII range 20h to 7Eh are shown as a full stop. The minimum number of bytes displayed is 16, regardless of the end address requested.
1234:8000 20 20 20 20 20 20 20 0D 0A 20 20 20 20 20 20 20 ..
1234:8010 20 20 20 20 20 20 20 20 20 63 46 34 2E 55 6E 2D cF4.Un-
1234:8020 64 65 6C 65 74 65 20 20 20 63 46 36 2E 54 6F 66 delete cF6.Tof
1234:8030 69 6C 65 2F 6D 61 72 6B 20 63 46 38 2E 52 69 67 ile/mark cF8.Rig
1234:8040 68 74 2D 66 6C 75 73 68 20 63 46 31 30 2E 53 77 ht-flush cF10.Sw
1234:8050 61 70 2D 66 69 6E 54 20 20 0D 0A OD 0A 0D 0A 4D ap-find ......M
1234:8060 45 4E 55 3A 20 20 68 65 6C 70 2C 20 65 78 69 74 ENU: help, exit
1234:8070 2F 63 6F 6D 6D 61 6E 64 2C 20 73 61 76 65 2F 75 /command, save/u
1234:8080 6E 73 61 76 65 3B 20 20 6E 61 6D 65 20 74 65 78 nsave; name tex
For brevity only the output for this first command is shown
D 2000:100 105
Displays 100h to 10Fh (the minimum 16 bytes) in segment 2000h.
D 1000 1580
Displays memory from 1000h to 157Fh inclusive in the current segment. If the dump command is subsequently used without parameters i.e.,
The next 128 bytes of memory from 1580h to 15FFh will be displayed. Further D commands entered without parameters will continue to display succeeding memory in blocks of 128 bytes.
E (<segment>:) <start offset>
This command is similar to the 'S(how)' command in the monitor. It displays memory at the specified location, allowing the contents to be examined or amended in hexadecimal or ASCII. A single display line of 16 bytes of memory is displayed in hex and ASCII formats, with the cursor initially under the first digit of the first byte specified.
Cursor movement and data entry is controlled as follows:
|←||moves cursor left.
If it is already at the far left of the display. the preceding 16 bytes are displayed.
|→||moves cursor right.
If it is already at the far right of the display, the next 16 bytes are displayed.
|↑||displays the next 16 bytes.
|↓||displays the preceding 16 bytes.
|Shift-←||moves the cursor immediately to the far left of the current display line.
|Shift-→||moves the cursor immediately to the far right of the current display line.
|ALT-DELETE||toggles between the hex and ASCII areas of the displayed data.|
The display consists of two 16-byte fields, a hexadecimal display and an ASCII display. ALT-DELETE keys toggle between the two fields (ie to switch between the two data formats ALT (ie the copy key) should be pressed down and held while DELETE is pressed). While the cursor is in the hex field, data is entered in hex digits, each digit being shifted in from the right.
To advance to the next field, the normal cursor keys are used. SHIFTed cursor keys are used to move to the far left or right of the current field. If the cursor is in the ASCII field, data is entered as ASCII bytes. The cursor is automatically advanced to the next field to allow text to be typed in directly. When text is entered at the far right of the field, the next 16 bytes are automatically displayed to allow typing to continue into the next 16 bytes.
If data is being entered in the ASCII field, control codes in the range 0 to 31 can be entered by pressing the appropriate key in conjunction with the CTRL key, eg CTRL-Z will enter the end of text marker 1Ah. The only exception is CTRL-C which terminates the command.
If the user wishes to enter CTRL-C or any other control greater than 7Fh, the entry should be made through the hexadecimal data field as pure hex digits.
3000:560 41 20 62 6F 74 20 6F 66 20 74 65 78 74 1A 07 00 A bot of text...
The spelling mistake in the text shown in the ASCII field can be corrected by either of the following two methods:
|1.||Move the cursor to the fourth byte in the hex field and enter the hex digits 6 and 9.
|2.||Use COPY-DEL to move to the ASCII field of the display, move to the fourth byte in this field and enter the character 'i'.|
CTRL-C terminates the command for either method.
The results of editing can conveniently be checked by using the dump command, when a large area of memory has been edited, as dump is capable of displaying all of the required portion of memory. Remember that CTRL-S can be used to halt the output, and any key will then resume it when more than a single screenfull is involved. For our simple one line example above, entering:
D 560 570
will display the required portion of memory for examination.
3000:560 41 20 62 69 74 20 6F 66 20 74 65 78 74 1A 07 0O A bit of text...
F(<segment>:) <start offset> <end offset> <fill byte|word>
This command is identical to the monitor's fill command. It fills the 512's memory with the supplied fill value, beginning at the the specified start offset and up to but not including the end offset.
Only the segment may be defaulted, both offsets and the fill value must be supplied, but an end offset of 0 can be used to specify a fill operation to the last byte in the specified segment. The fill value supplied may be specified either as a byte or as a word (two bytes). Fill bytes must be given as hexadecimal values, strings are not permitted. If a word value is specified the least significant byte is written first.
F 3000:1000 1010 55
will fill bytes 1000h to 1001h indusive in segment 3000: with the byte value 55h.
F 0 1010 1234
will fill bytes 1000h to 100Fh inclusive in the current (default) segment with the word value 1234h, with the least significant byte written first, that is, the contents of memory will be:
3000:0000 34 12 34 12 34 12 34 12 34 12 34 12 34 12 34 12
F 4030:1300 0 20
will fill the remainder of segment 4000: from offset 1000h, with spaces (20h)
Displays the help list of EDBIN commands. The H command displays the EDBIN version number and a list of available commands with their required syntax. There are no parameters. See above for sample output.
M (<segment>:) <src start> <src end> (<segment>:) <dest start>
This EDBIN command has no monitor equivalent. It moves (ie copies) the block of memory specifed to a specifed destination address.
The block of memory at the source address is not generally affected by the move, it is simply copied to the given address. If an overlapping move is specified (a move where part of the destination block overlaps the source block) the data that will be overwritten by the operation is always moved first to ensure that the destination data is correct. In such moves it is inevitable that the source block must be corrupted in the overlapping area.
M 2000:100 740 1200:10
moves 640h bytes from 100h to 73Fh in segment 2000h to the memory block beginning at address 10h in segment 1200h.
M 100 740 1200:10
Exactly as in the previous command, except that the move in this case is from the current (default) segment. As before 640h bytes are moved from 100h to 73Fh to address 10h in segment 1200h.
Exits EDBIN and returns to the DOS Plus command line prompt or the calling routine. The Q command has no parameters. It closes the currently active file (if one exists), restores the calling DOS Plus environment and returns to the caller (usually the DOS Plus command line).
This command has no monitor equivalent, as you can use *LOAD at the monitor level. It reads a named file into memory for examination and possible amendment. The specified file is read into memory at the start of the file buffer. This can always be located by a D command with no parameters, when the segment address, used by default, is the buffer's address. The default segment is always reset when a new file is loaded.
The size of the file and the number of bytes actually read are displayed as the file is being loaded into memory. These two numbers should normally be the same but, in the event of a disc error, the number of bytes read will indicate how much of the file has been read.
When a file is loaded by using the Read command (or was loaded by adding the filename to the initial EDBIN command) the specified <filename> becomes the currently active file (CAF). This will remain the active file until a subsequent Read operation closes the CAF, when the newly loaded file becomes the new CAF. If EDBIN was initially executed with a filename added to the command line for immediate load, that automatically becomes the Currently Active File. (For further information on the the Currently Active File see the Write command).
loads the file PROFILE.EXE into memory at the start of the file buffer and resets the current command segment/offset variables, so that file editing default addresses operate on the file buffer.
EDBIN always loads all file images into memory at the start of its file buffer, regardless of the file type. Neither CMD or EXE files have the file header stripped.
The entire file is loaded into memory exactly as it is stored on disc. The user should remember that in the case of CMD and EXE files, the start of the code segment is offset by the length of the file header, and the file header should not normally be amended for executable files.
(See Chapter 7 for executable file types and header information)
S (<segment>:) <start offset> <end offset> <"string">
This command operates exactly like the monitor's SR command. It searches memory between the specified address limits attempting to match the supplied string, the search argument which must be enclosed by double quotes against memory contents. The end offset specified is the end address+1 of the search area, so to allow the search to continue to the end of a segment an end address of 0 can be specified.
Each complete occurence of the string found between the specified limits causes a displayed report of the start address for each match. The addresses of matched strings are shown in normal segment:offset format. The search string maybe up to a maximum of 72 characters in length and it must be remembered that the search argument is case sensitive.
This command is useful for locating known data which can be easily or uniquely identified, for example, a key phrase or literal in a program file. Note that each iteration of the search is confined to the specified (or defaulted) segment. A multipIe-segment search must therefore be carried out as a number of separate searches. After locating the string, the Dump command can be used to display a larger section of memory to ensure the correct location has been found.
S 3000:400C 0 "myprog.com"
searches from 4000h to 0FFFFh inclusive in segment 3000h, attempting to match the text string 'myprog.com'. The condition for a string to be matched is that it must be completely contained within the search area, ie if string 'myprog.com' begins only at at 03FFAh then:
S 3000:0 4000 "myprog.com"
will not locate it since it is not entirely contained within the specified search limits. If, however, the string began at an offset address of 03FF6h or lower, the above search would locate it. Any string consisting of 8-bit characters can be searched for, using escape sequences to allow inclusion of control codes and characters above 07Fh (these are compatible with the MOS escape sequences). The | character is used to denote an escape sequence.
The following table summarises the range of control code specifications between 00h and 7Fh:
|"|a" or "|A"||1|
|"|z" or "|Z"||1A
|Table 11.2 Control Code Specifications (00h to 7Fh).|
|Exceptions are the following three special cases:|
|"||"||7C (vertical bar)|
|Characters of 80h and above are entered by preceding the seven bit value with the |! operator, ie|
|"|!<char>"||80 to FF|
where <char> is any character between 00h and 7Fh, thus 0FFh would be entered as |!|?
Note that all characters in the search are case dependent, including escape sequences. Unrecognised escape arguments are reduced to the argument alone and any surplus or redundant | operators are ignored. For example
||1||is reduced to 1|
||!|!|@||is reduced to |!|@|
Any string not terminated by a double quote character, or which contains an odd number of double quote characters, will be reported as a bad string, eg
|String||Reason for error|
|"abc||No terminating quote|
|"ab""||Single quote character in string|
|"ab"""c"||Odd number of quotes|
A Bad string error is also generated if no argument is supplied for the escape character |, or if a null string or the equivalent is specified, eg
|String||Reason for error|
|"a|"||No escape argument|
|"|!"||Reduces to null string, hence as above|
The search operation can be stopped at any time by pressing CTRL-C.
S 100 7B00 "a text string"
will search from 100h to 7AFFh for the string "a text string". Any occurrences of the string in the specified section of memory will be reported in the form:
Writes the specified file or currently active file to a disc file.
If the W command is used with no filename, the modified data in memory is written back to the currently active file, the file that was specified in the last a command. If a filename is specified the data is written instead to this specified file, but note that, using the W command with a supplied (different) filename does not affect the currently active filename.
This means that subsequent W commands with no filename will write the data to the original filename specified in the last R command. This permits several saves of a file during editing, for security, and until completion the file can be saved to a work file if required, rather than the original file. Note that normal rules apply. If you write to a new filename it will be created, but if you write to an existing filename, if the file has write permission it will be overwritten.
When writing the file, the number of bytes written is displayed on the screen. If EDBIN cannot write all the bytes to the file an error message is displayed to indicate the problem.
writes data from the file buffer to the currently active filename. The number of bytes written is equal to the length of the file loaded by the R command.
writes the currently active file to a file called WORKFILE.TMP. if this file does not exist it will be created. If it does exist it will be overwritten, except as shown below.
The R command has been used to try and read a file that does not exist on the disc, or the full path name for the file has not been specified.
The R <filename> or W <filename> command has been used to read or write a file in a directory that does not exist.
The R command or W <filename> command has been used to try to open a file when there are already 20 open files. This error should not normally occur, and it will only happen if some previous application has not closed its files on exit. EDBIN requires only two files open at any time.
The R command has been used on a Read Only file. The R command attempts to open a file for R/W access, on the assumption that the user will probably want to write the modified data back to the file. To prevent this error, the file should be set to R/W using FSET before entering EDBIN.
This error may also occur if W <filename> has been used to write to a file that has the same name as an existing file that is marked R/O, or if the specified directory is full.
The W command has been used when there is no Currently Active File to write the data to. The CAF must be activated by an R command, or by specifying a filename in the command line when EDBIN is first called.