See our Tech Notes on the difficulty of working with versions 1.10 and 1.00 of IBM®'s Personal Computer DOS.
NOTE: The FORMAT.COM file (05-07-1982; 3,816 bytes; MD5: 31B9C8001D7E9D9E98808B93BADF4B98) contains an exact copy of the Boot Sector; it's located at offsets BE8h through DE7h within that file. In an image file of the whole diskette, it can be found at offsets 4FE8h through 51E7h.
Unlike later versions of DOS, 1.10 (and 1.00) never contained a BPB (BIOS Parameter Block; though it appears to have a pre-cursor for one) nor what has become the standard Boot Signature (AA55h) at the end of almost every other DOS Boot Sector. These differences mean that most utility programs and even MS-DOS versions running in PC Compatibles as well as the Microsoft™ Windows® Operating Systems will consider these diskettes to be incorrectly formatted; even though their FAT12 file system is basically the same as the ones found on later MS-DOS diskettes! As we pointed out on our Tech Notes page, the main reason for this problem has to do with the so-called "compatibles" not containing actual clones of the IBM PC ROM chips, and deciding not to support the old IBM diskette capacities.[1]
IBM PC DOS 1.10 was only distributed on 160 KiB single-sided diskettes. However, it was possible to create a 320 KiB system boot diskette in a double-sided B: drive, if your IBM PC had one. Such a diskette has only a two-byte difference in its Boot Sector beginning at offset 003h, where the bytes "08 00" are changed to: "03 01" for a 320 KiB diskette. Instructions for creating a 320 KiB boot diskette using PCE (and its IBM PC DOS 1.10 image file) can be found here.[2]
Absolute Sector 0 (Track 0, Side 0, Sector 1) 0 1 2 3 4 5 6 7 8 9 A B C D E F 0000 EB 27 90 08 00 14 00 00 00 00 00 00 00 00 00 00 .'.............. 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0020 00 00 00 00 00 00 00 CD 19 FA 8C C8 8E D8 33 D2 ..............3. 0030 8E D2 BC 00 7C FB B8 60 00 8E D8 8E C0 33 D2 8B ....|..`.....3.. 0040 C2 CD 13 72 69 E8 85 00 72 DD 2E 83 3E 03 7C 08 ...ri...r...>.|. 0050 74 06 2E C6 06 64 7D 02 BB 00 00 2E 8B 0E 03 7C t....d}........| 0060 51 B0 09 2A C1 B4 00 8B F0 56 33 D2 33 C0 8A C5 Q..*.....V3.3... 0070 2E F6 36 64 7D 8A E8 8A F4 8B C6 B4 02 CD 13 72 ..6d}..........r 0080 2D 5E 59 2E 29 36 05 7C 74 1F 8B C6 2E F7 26 65 -^Y.)6.|t.....&e 0090 7D 03 D8 FE C5 B1 01 51 BE 08 00 2E 3B 36 05 7C }......Q....;6.| 00A0 7C 05 2E 8B 36 05 7C EB C0 EA 00 00 60 00 BE 67 |...6.|.....`..g 00B0 7D E8 02 00 EB FE 32 FF 2E AC 24 7F 74 0B 56 B4 }.....2...$.t.V. 00C0 0E BB 07 00 CD 10 5E EB EF C3 E9 33 FF BB 00 00 ......^....3.... 00D0 B9 04 00 B8 01 02 CD 13 1E 72 33 8C C8 8E D8 BF .........r3..... 00E0 00 00 B9 0B 00 26 80 0D 20 26 80 4D 20 20 47 E2 .....&.. &.M G. 00F0 F4 BF 00 00 BE 8B 7D B9 0B 00 FC F3 A6 75 0F BF ......}......u.. 0100 20 00 BE 97 7D B9 0B 00 F3 A6 75 02 1F C3 BE 1B ...}.....u..... 0110 7D E8 A2 FF B4 00 CD 16 1F F9 C3 0D 0A 4E 6F 6E }............Non 0120 2D 53 79 73 74 65 6D 20 64 69 73 6B 20 6F 72 20 -System disk or 0130 64 69 73 6B 20 65 72 72 6F 72 0D 0A 52 65 70 6C disk error..Repl 0140 61 63 65 20 61 6E 64 20 73 74 72 69 6B 65 20 61 ace and strike a 0150 6E 79 20 6B 65 79 20 77 68 65 6E 20 72 65 61 64 ny key when read 0160 79 0D 0A 00 01 00 02 0D 0A 44 69 73 6B 20 42 6F y........Disk Bo 0170 6F 74 20 66 61 69 6C 75 72 65 0D 0A 00 4D 69 63 ot failure...Mic 0180 72 6F 73 6F 66 74 2C 49 6E 63 20 69 62 6D 62 69 rosoft,Inc ibmbi 0190 6F 20 20 63 6F 6D 30 69 62 6D 64 6F 73 20 20 63 o com0ibmdos c 01A0 6F 6D 30 05 C6 06 77 2F FF 83 7E FC 00 75 0B 80 om0...w/..~..u.. 01B0 7E F7 3B 75 05 C6 06 76 2F FF 89 EC 5D CA 04 00 ~.;u...v/...]... 01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0 1 2 3 4 5 6 7 8 9 A B C D E F |
The string you see from offset 017Dh through 018Ah ("Microsoft, Inc ")
replaced
the name of the Boot Sector's author in the previous version (cf. version 1.00).
The two underlined ASCII "0" bytes (30h) following each of the System file names
(at offsets 196h and 1A2h) are not used in any
of the code below. For a discussion
on how they got there, see our comments on the PC DOS 1.00 Boot Sector here.
The hex bytes shown above in DARK RED italics, are never accessed in any way by the code. After examining and discussing the code with others, it was our opinion that these bytes (at offsets 01A3h through 01BEh) were simply junk bytes that should have been zeroed-out before mass producing the distribution diskette! Then next question was: "But, they only appear on original distribution diskettes (or exact copies), right?" Wrong! It turned out, and you should have already guessed this from my comments further above where I wrote, "...contains an exact copy of the Boot Sector," that these bytes were also included in FORMAT.COM, so were written to every newly formatted diskette! So, which came first? Was it a dirty Boot Sector that someone copied into FORMAT.COM (without ever checking it), or a corrupted FORMAT.COM used to make the Master distribution diskette? For the most plausible answer, see the Conclusion: section below.
Finally, on December 9, 2021, I wondered if these were truly random bytes, or if they were actually part of an x86 program. And if so, could I ever find it? As any assembly programmer knows, some code is always the same no matter where it's located in a program, yet, other code is very much dependent upon its location and the offset it has from the code around it. Well, I quickly discovered some repeating bytes that make sense no matter where they occur, and they are also part of the last 6 bytes here; when including a zero byte at the end, "89 EC 5D CA 04 00" which disassemble into:
89EC MOV SP,BP 5D POP BP CA0400 RETF 0004
Apart from the Boot Sector and FORMAT.COM, these appear no less than 14 times elsewhere on the diskette. Without trying to find any meaning in those locations, I began searching for similarities to the whole string we'd labeled as junk (or garbage) bytes. After searching again, I identified the program they must have originated from! Here are the former junk bytes from the Boot Sector, followed by the same number of bytes (which happen to be the very last bytes; including 17 zero bytes), from the end of a program in Absolute Sector 166, beginning at offset 14D53:
0 1 2 3 4 5 6 7 8 9 A B C D E F 001A3 05 C6 06 77 2F FF 83 7E FC 00 75 0B 80 001B0 7E F7 3B 75 05 C6 06 76 2F FF 89 EC 5D CA 04 00 001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 1 2 3 4 5 6 7 8 9 A B C D E F 14D53 05 C6 06 57 30 FF 83 7E FC 00 75 0B 80 14D60 7E F7 3B 75 05 C6 06 56 30 FF 89 EC 5D CA 04 00 14D70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
These are the last 45 bytes of the program: LINK.EXE.[3] This program also includes 35 occurrences of
the string "89 EC 5D CA 0H 00"; with H representing 02 (10 times), 06 (9
times), 08 (6 times), 0A (6 times), 0C (3 times) and 0E (once).
Conclusion: I don't see how the 25 matching bytes in the same positions (41 if we include the 16 zero bytes at the end) could possibly be a coincidence!
So, How did what appears to be only a slightly different version of the end of the largest program on the diskette (41,856 bytes) show up in its Boot Sector? I believe this
segment of code, during the development of LINK.EXE, became part of the Slack Space of FORMAT.COM during its own development, and rather than determining exactly what was supposed to be in
the Boot Sector, that Slack Space then became part of FORMAT.COM's copy of the Boot Sector; which was later used to format another working diskette that eventually became the
distribution diskette!
As evidence to support that claim, on January 5, 2022, I discovered that the unused code at the end of FORMAT.COM was also highly likely a part of LINK.EXE during its development: That code had
no apparent connection to any of the code before the copy of the Boot Sector bytes in FORMAT.COM, so I began searching for a similar pattern of code elsewhere on the diskette. I found such a pattern
within LINK.EXE which although not 100% conclusive, I think you will agree it's highly probable (just as the former "junk bytes" at the end of the Boot Sector were), that these bytes
came from an earlier version of LINK.EXE as shown on this page. In fact, if you shorten the length of FORMAT.COM from 3,816 bytes (and 4,096
allocated) to 3,560 bytes, 256 bytes less (and only 3,584 allocated), by manually editing the size in its Directory entry and trimming the FATs (pun intended); necessary, since it needs to
have a cluster removed from its file length, FORMAT.COM will still function the same as before.
What it does:
1. Initializes critical registers and checks if the floppy drive is responding (7C297C43).
2. Checks for a System Boot disk in floppy drive (7C45, 7CCD7D0D),
notifies user if none found (7D0E & 7D11 and 7CB67CC9) and
waits for user to try another disk (7D147D1A and 7C48); using a longer process than PC DOS
1.00, including INT 19h (at 7C27), re-initializing registers and resetting the disk drive, until a
System Boot disk is found, or user powers off the PC.
3. Loads System files (IBMBIO.COM and IBMDOS.COM) and 2 sectors (for 320 KiB diskettes) or 3 sectors
(for 160 KiB diskettes) of whatever follows[4] into Memory (at 0000:0600 through 0000:2DFF) using:
(7C587C67) to initialize registers for copying sectors into Memory,
(7C697CA7) to copy all the System code into Memory (in four passes for single-sided
160 KiB diskettes, and only 3 passes for 320 KiB dual-sided diskettes).
4. If an error occurs while copying System files, the code at 7C7F, 7CAE7CB4, and
the Display subroutine (7CB67CC9) handle the disk error.
5. If no fatal error occurs, starts executing the IBMBIO.COM file in Memory (see: 7CA9).
Here's a disassembly of the code (; with comments on every assembly instruction)
after
being loaded into Memory at locations 0000:7C00 through 0000:7DFF by the PC's BIOS:
(Comments on the code which occur with this background
color, apply only to 320 KiB boot diskettes / image files.)
7C00 EB27 JMP 7C29 ; Jump over reserved data area 7C02 90 NOP ; Do nothing; never executed.
Data Locations which Code Execution Jumps Over: 0 1 2 3 4 5 6 7 8 9 A B C D E F 7C03 08 00 14 00 00 00 00 00 00 00 00 00 00 ............. 7C10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 7C20 00 00 00 00 00 00 00 ....... Or, for a 320 KiB Diskette: 0 1 2 3 4 5 6 7 8 9 A B C D E F 7C03 03 01 14 00 00 00 00 00 00 00 00 00 00 ............. 7C10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 7C20 00 00 00 00 00 00 00 .......
; This code segment can only be executed from Memory offset 7C48 : 7C27 CD19 INT 19 ; System Boot disk not found, ; so, Start over again with ; System BOOTSTRAP LOADER. ; Normal code execution begins here: 7C29 FA CLI ; Disable maskable Interrupts 7C2A 8CC8 MOV AX,CS ; Zero-out the Accumulator & 7C2C 8ED8 MOV DS,AX ; set Data Segment to ZERO. 7C2E 33D2 XOR DX,DX ; Zero-out DX and use it to 7C30 8ED2 MOV SS,DX ; set Stack Segment -> 0000 7C32 BC007C MOV SP,7C00 ; Set Stack Pointer to: 7C00 7C35 FB STI ; Enable Interrupts 7C36 B86000 MOV AX,0060 ; 0060h -> AX 7C39 8ED8 MOV DS,AX ; 0060h -> DS 7C3B 8EC0 MOV ES,AX ; 0060h -> ES 7C3D 33D2 XOR DX,DX ; Zero-out DX & use it to 7C3F 8BC2 MOV AX,DX ; set: AX = 00 (Function 00 ; RESET DRIVES, of INT 13). 7C41 CD13 INT 13 ; Reset Floppy Disk drives; if ; CF=1(set) there's an error. 7C43 7269 JC 7CAE ; If CF is set, jump to Drive ; failure routine; otherwise: 7C45 E88500 CALL 7CCD ; Is this a System Boot disk? 7C48 72DD JC 7C27 ; If not, execute INT 19, after ; waiting for keypress at 7D16; ; and start all over again! 7C4A 2E833E037C08 CMP WORD PTR CS:[7C03],+08 ; [7c03] = 0008, 7C50 7406 JZ 7C58 ; so go to 7C58. ;--------------------------------------------------------------------- ; This instruction will only be executed if WORD [7C03] is not 0008; 7C52 2EC606647D02 MOV BYTE PTR CS:[7D64],02 ; A properly formatted 320 KiB (PC DOS 1.10) diskette will have 0103 ; as that WORD. So, [7D64] will become "02". ;--------------------------------------------------------------------- ;===================================================================== ; INT 13, Function 02 (AH=02) parameters: ; Copies sectors from disk into Memory; using Track, Side & Sector: ; ; (IN): ; AL = Number of Sectors to read ; CH = Track number ; CL = Starting Sector number (bits 0-5) ; DH = Side number ; ES:BX = Start of Memory to copy sectors to ; ; If CF = 1 (set), then there was a read error! ;===================================================================== 7C58 BB0000 MOV BX,0000 ; Copy into ES:BX (0060:0000; ; same as Memory Address 0600) 7C5B 2E8B0E037C MOV CX,CS:[7C03] ; Copy 0008 into CX and... ; Copy 0103 into CX and... 7C60 51 PUSH CX ; Save it on the Stack; ; note: CH = 00 here. ; note: CH = 01 here. 7C61 B009 MOV AL,09 ; Put "09" into AL 7C63 2AC1 SUB AL,CL ; 09 - 08 = 01 (in AL) ; 09 - 03 = 06 (in AL) 7C65 B400 MOV AH,00 ; Ensure AH byte is zero. 7C67 8BF0 MOV SI,AX ; 0001 -> SI ; 0006 -> SI ;=========================================================================== ; System Files Loading Loop ;=========================================================================== 7C69 56 PUSH SI ; Saved on Stack for use below ... ; 1st pass: SI = 0001 (from 7C67). ; On 2nd, 3rd & 4th passes: SI = 0008, 0008 and 0003 respectively, which ; correspond to the number of sectors copied during 3 subsequent loops ; for a total of 1 + 8 + 8 + 3 = 20. 1st pass: SI = 0006 (from 7C67). ; On 2nd & 3rd passes: SI = 0008 and 0006, respectively, which correspond ; to the number of sectors copied, so all 20 sectors are copied in only ; three passes for a 320 KiB diskette. 7C6A 33D2 XOR DX,DX ; (DH = 0 for Side 0 of diskette; ; can change for 320 KiB at 7C77.) 7C6C 33C0 XOR AX,AX ; Zero-out AX register. ;----------------------------------------------------------------------------- ; The following code only affects the results if the code at 7C52 is executed; ; that is: Only if booting a DOS 1.10 /S (System) formatted 320 KiB diskette. 7C6E 8AC5 MOV AL,CH ; 1st pass: CH=00 -> AL (for all other ; passes, AL is set to: 01, 02 and 03 ; corresponding to the Track Numbers that the sectors are copied from.) ; The results are different for 320 KiB ; diskettes, since AL is divided by [7D64] = 02 (with CH = 01, 02 and 03): 7C70 2EF636647D DIV AL,BYTE PTR CS:[7D64] ; 1st pass: 0/1 = 0 -> AL ; on the 2nd, 3rd and 4th ; passes, 1/1 = 1, 2/1 = 2 and 3/1 = 3, so AL is the same as it was in 7C6E. ; 1st pass: 1/2 = 0 -> AL ; (but AX = 0100 [256]. Why? Because unsigned 8-bit division puts remainders ; into AH register). 2nd pass: 2/2 = 1 -> AL and the 3rd pass: 3/2 = 1 -> AL ; (with another remainder of 1 in AH, so AX = 0101 [or 257]). 7C75 8AE8 MOV CH,AL ; CH also remains the same for all 4 ; passes: 1st pass: 00 -> CH, and on ; the 2nd, 3rd and 4th passes: 01, 02 and 03 -> CH ; However, for 320 KiB diskettes, the Track Numbers are: CH = 0 (1st pass), ; but then CH = 01 for both the 2nd and 3rd (last) passes. ; For 160 KiB diskettes, the following instruction is irrelevant, since AH ; is always zero here. But AH changes at 7C70 for 320 KiB diskettes, so... 7C77 8AF4 MOV DH,AH ; 1st pass: AH (01; see above) -> DH; ; IBMBIO.COM is on Side 1 of diskette. ; 2nd pass: AH and DH are back to zero (for Side 0), but on the 3rd pass: ; AH and DH are both 01 (for Side 1) once again! ;----------------------------------------------------------------------------- ; For all of the sector-copying after the first pass, the CH and CL registers ; are set by the code further below at 7C93 through 7C97 !!! 7C79 8BC6 MOV AX,SI ; 1st pass: 0001 -> AX (1 sector will be ; copied into 0600 through 07FF), 2nd pass: ; 0008 -> AX (8 sectors copied into 0800 through 17FF), 3rd pass: 0008 -> AX (8 ; more sectors copied into 1800 through 27FF; note: 511 zero bytes at end here!) ; 4th pass: 0003 -> AX (only 3 more sectors copied into 2800 through 2DFF). One ; can't help but ask: "Why the first 3 sectors of COMMAND.COM?" Answer: The only ; plausible explanation is, that at that time, it was the easiest way they could ; find for the Boot Sector to load IBMBIO and IBMDOS into Memory! As was pointed ; out for PC DOS 1.00, these 3 sectors are never used at these Memory locations. ; lst pass: 0006 -> AX (6 sectors will be ; copied into 0600 through 11FF), 2nd pass: ; 0008 -> AX (8 sectors will be copied into 1200 through 21FF). On the 3rd (and ; final) pass: SI = 0006 -> AX, so 6 sectors are copied into 2200 through 2DFF. 7C7B B402 MOV AH,02 ; Function 02 of INT 13 7C7D CD13 INT 13 ; Unless a disk read error occurred (handled below at 7C7F), the code and INT13 ; above copied the first sector of IBMBIO.COM (Absolute Sector 7) into Memory ; locations 0000:0600 through 07FF; overwriting the Directory entries that had ; been temporarily saved there. Subsequent passes copy the remaining 3 sectors ; of IBMBIO.COM, 13 sectors of IBMDOS.COM and 3 sectors of whatever follows it. ; The code above will copy all four sectors of IBMBIO.COM (Sectors 322-325) and ; the first 2 of IBMDOS.COM (Sectors 326-327); Clusters 2-4, from Side 1 of the ; diskette into Memory locations 0000:0600 through 11FF; overwriting Directory ; entries that had been temporarily saved in 0600-07FF. The subsequent 2 passes ; copy Clusters 5- 8 (Sectors 8-15) of IBMDOS.COM (8 more sectors) from Side 0, ; then Clusters 9-11 (Sectors 328-333) from Side 0; the remaining 4 sectors of ; IBMDOS.COM (which is an extra sector longer due to clusters being 1024 bytes, ; wasting that sector) and lastly, two sectors (Sectors 332-333) of whatever is ; there. It obviously doesn't matter if only 2 instead of 3 sectors are copied, ; because none of what's in them is ever used in these Memory locations.[5] 7C7F 722D JC 7CAE ; If disk read error (CF=1), ; jump to error handling routine. 7C81 5E POP SI ; Restore SI -> 0001 (1st pass), 0008 ; (2nd), 0008 (3rd), 0003 (4th pass). ; Restore SI -> 0006 (1st pass), 0008 ; (2nd pass) and 0006 for 3rd pass! 7C82 59 POP CX ; Restore CX -> 0008 (1st pass), 0101 ; (2nd), 0201 (3rd), 0301 (4th pass). ; Restore CX -> 0103 (1st pass), 0201 ; (2nd), 0301 (for final 3rd pass). 7C83 2E2936057C SUB CS:[7C05],SI ; 1st pass: 20 - 1 = 19 ([7C05]=0013), 2nd: 19 - 8 = 11 ([7C05]=000B), ; 3rd: 11 - 8 = 3 ([7C05]=0003). 4th: 3 - 3 = 0 ([7C05]=0000). ; 1st pass: 20 - 6 = 14 ([7C05]=000E), 2nd: 14 - 8 = 6 ([7C05]=0006), ; 3rd: 6 - 6 = 0 ([7C05]=0000). 7C88 741F JZ 7CA9 ; Finished loading System code. 7C8A 8BC6 MOV AX,SI ; For all 3 passes, there is no ; change in contents of AX reg! 7C8C 2EF726657D MUL AX,WORD PTR CS:[7D65] ; 1st pass: 0200h (512) -> AX, 2nd pass: 8 x 0200h = 1000h (4096 in AX), ; 3rd pass: 0008 x 0200h = 1000h (4096 into AX again). ; 1st pass: 0006 x 0200h = 0C00h (3072 in AX), ; 2nd pass: 0008 x 0200h = 1000h (4096 in AX); no 3rd pass! 7C91 03D8 ADD BX,AX ; 1st pass: (0000)+ AX(0200) -> BX ; 2nd: BX (0200) + AX(1000) -> BX, ; making it 1200h (or 4608 or 9 sectors), 3rd pass: BX (1200) + AX (1000) ; -> BX (now 2200h, or 8704 or 11 sectors). ; 1st pass: (0000)+ AX(0C00) -> BX ; 2nd pass: BX (0C00) + AX(1000) = 1C00 -> BX (7168); no 3rd pass! 7C93 FEC5 INC CH ; For the 1st, 2nd & 3rd loops: ; CH -> 01, 02 and 03. Only 2 ; passes: CH -> 02 and 03. 7C95 B101 MOV CL,01 ; Always Sector 1 for any Track. 7C97 51 PUSH CX ; 1st pass: CX = 0101 (CX = 0201), ; 2nd pass: CX = 0201 (CX = 0301), ; 3rd pass: CX = 0301 . 7C98 BE0800 MOV SI,0008 ; Read up to 8 sectors maximum. 7C9B 2E3B36057C CMP SI,CS:[7C05] ; To bypass 7CA2 or not? ; 1st pass: CMP: 0008 < 0013 -> CF set [CMP: 0008 < 000E -> CF set] ; 2nd pass: CMP: 0008 < 000B -> CF set [CMP: 0008 > 0006 --|] ; 3rd pass: CMP: 0008 > 0003 so no bypass, execute 7CA2. <---| 7CA0 7C05 JL 7CA7 ; Bypass next instruction on 1st ; & 2nd passes, but not the 3rd: ; Bypass on 1st pass; not on 2nd: 7CA2 2E8B36057C MOV SI,CS:[7C05] ; [7C05] = 0003 -> SI, and then... ; [7C05] = 0006 -> SI 7CA7 EBC0 JMP 7C69 ; Loop back to copy more... ; System code into Memory ; ------------------------------------------------------------------------ ; Transfer Code Execution to IBMBIO.COM (at 0000:0600): 7CA9 EA00006000 JMP FAR 0060:0000 ; -> 0000:0600 (the first byte ; of IBMBIO.COM ) ; ------------------------------------------------------------------------ ;=========================================================================== ; Boot Disk Error Handling Routine: ;=========================================================================== 7CAE BE677D MOV SI,7D67 ; -> 0D,0A,"Disk Boot failure" 7CB1 E80200 CALL 7CB6 ; Display Error Message & Return 7CB4 EBFE JMP 7CB4 ; Locks-up execution in ; never ending loop!! ;=========================================================================== ; Display Zero-terminated String Subroutine: ;=========================================================================== ;========================================================================== ; Function 0Eh = TELETYPE OUTPUT -> Display one character at a time ; (IN): ; AL = character to display ; BH = page number (IBM PC ROMs dated 4/24/81 and 10/19/81 ; require BH be the same as the current active page) ; BL = foreground color (graphics modes only) ;========================================================================== 7CB6 32FF XOR BH,BH ; Page 0 7CB8 2EAC LODSB AL,BYTE PTR CS:[SI] ; Moves one string byte ; character into AL ; and increments SI. ;--------------------------------------------------------------------------- ; Although the error messages on this boot diskette have no characters with ; a high bit; like they did under IBM PC DOS 1.00, the same instruction used ; there still has two necessary functions: 1) It sets the zero-flag if a 00 ; byte is read; which is the only way to exit this subroutine at 7CBC below. ; (It could still convert high bit characters if necessary.) And 2) The XOR ; instruction at 7CB6 also sets the zero-flag, so this logic instruction is ; required to unset it, or no message bytes would ever be displayed.[6] 7CBA 247F AND AL,7F ; If AL contains a zero-byte, ZF -> 1 ;--------------------------------------------------------------------------- 7CBC 740B JZ 7CC9 ; Return if zero-flag set (ZF = 1). 7CBE 56 PUSH SI ; Save new SI value on Stack 7CBF B40E MOV AH,0E ; Function 0Eh of INT 10 7CC1 BB0700 MOV BX,0007 ; Light Gray or White character 7CC4 CD10 INT 10 ; Display character on screen 7CC6 5E POP SI ; Restore SI from Stack 7CC7 EBEF JMP 7CB8 ; Get next character 7CC9 C3 RET ;------------------------------------------------------------------------ ; When is this code ever executed? ; (Is there a Jump to here from IBMBIO.COM or some other code?) 7CCA E933FF JMP 7C00 ; Start the Boot Sector code ; in Memory all over again! ;------------------------------------------------------------------------ ;=========================================================================== ; Check for System Boot Disk ;=========================================================================== ;================================================================== ; INT 13, Function 02 (AH=02) parameters: ; Copies sectors from disk into Memory; using Track, Side & Sector: ; ; (IN): ; AL = Number of Sectors to read ; CH = Track number ; CL = Starting Sector number (bits 0-5) ; DH = Side number ; ES:BX = Start of Memory to copy sectors to ; ; If CF = 1 (set), then there was a read error! ;================================================================== 7CCD BB0000 MOV BX,0000 ; Copy into: ES:BX (0060:0000; ; same as Memory Address 0600) ; DX still zero, so: Side 0, 7CD0 B90400 MOV CX,0004 ; Track 0 and Sector 4. ; (Beginning of Directory) 7CD3 B80102 MOV AX,0201 ; AL=01, (Read 1 Sector only) 7CD6 CD13 INT 13 ; Unless a disk read error occurred (handled below at 7CD9), then all ; 512 bytes of the 4th sector (Absolute Sector 3) have been read into ; Memory locations 0000:0600 and following, and the ; first two Directory entries (of 32 bytes each) should appear as: ; ----------------------------------------------------------------------- ; 0600 49 42 4D 42 49 4F 20 20 43 4F 4D 06 00 00 00 00 IBMBIO COM..... ; 0610 00 00 00 00 00 00 00 60 A7 04 02 00 80 07 00 00 .......`........ ; 0620 49 42 4D 44 4F 53 20 20 43 4F 4D 06 00 00 00 00 IBMDOS COM..... ; 0630 00 00 00 00 00 00 00 60 A7 04 06 00 00 19 00 00 .......`........ ; ; Apart from the highlighted bytes; which DOS interprets as the date May ; 7, 1982 (or "5-07-82"), the lengths of these two files (0780h = 1,920; ; 1900h = 6,400) are exactly the same as they were for IBM PC DOS 1.00. ; ----------------------------------------------------------------------- 7CD8 1E PUSH DS ; Save DS (0060h) on Stack 7CD9 7233 JC 7D0E ; If CF=1 (set), Disk Read Error ; Jump to Error handling routine 7CDB 8CC8 MOV AX,CS ; CS -> AX (should be 0) 7CDD 8ED8 MOV DS,AX ; AX -> DS (should be 0) 7CDF BF0000 MOV DI,0000 ; Zero-out DI (start @ 0 offset) 7CE2 B90B00 MOV CX,000B ; 0Bh = 11 (Number of filename ; characters to process below.) 7CE5 26800D20 OR BYTE PTR ES:[DI],20 ; Convert any ASCII ; "A-Z" bytes into ; lower case [a-z]. 7CE9 26804D2020 OR BYTE PTR ES:[DI+20],20 ; Does the same (Note: [DI+20] is in hex, +20h = +32) ; for 2nd entry ; in Directory. 7CEE 47 INC DI ; Add 1 to DI -> next character 7CEF E2F4 LOOP 7CE5 ; Loop until all 11 characters ; in both entries are processed 7CF1 BF0000 MOV DI,0000 ; Set offset to zero again. 7CF4 BE8B7D MOV SI,7D8B ; -> "ibmbio com" 7CF7 B90B00 MOV CX,000B ; Compare 11 characters below. 7CFA FC CLD ; Clear Direction Flag; ensure ; SI and DI increment below. 7CFB F3 REPZ ; Repeat CMPSB CX times: 7CFC A6 CMPSB ; Compare byte ES:[DI] to DS:[SI] 7CFD 750F JNZ 7D0E ; If not identical, this is not ; a System Boot Disk, so jump to ; error handling routine (7D0E) 7CFF BF2000 MOV DI,0020 ; Set offset (DI) to 020h (32) ; for second Directory entry. 7D02 BE977D MOV SI,7D97 ; -> "ibmdos com" 7D05 B90B00 MOV CX,000B ; 11 times again... 7D08 F3 REPZ 7D09 A6 CMPSB 7D0A 7502 JNZ 7D0E ; Not a System Boot Disk! ; Jump to error handling routine 7D0C 1F POP DS ; Restore Data Segment 7D0D C3 RET ;=========================================================================== ; Non-System Disk or Disk Error Handling Routine: ;=========================================================================== 7D0E BE1B7D MOV SI,7D1B ; -> 0D,0A,"Non-System disk" etc. 7D11 E8A2FF CALL 7CB6 ; Display error message & return 7D14 B400 MOV AH,00 7D16 CD16 INT 16 ; Wait for keypress 7D18 1F POP DS ; Restore Data Segment 7D19 F9 STC ; Set the Carry Flag (CF=1) to ; notify code at 7C48 of error! 7D1A C3 RET
B C D E F 7D1B 0D 0A 4E 6F 6E ..Non 7D20 2D 53 79 73 74 65 6D 20 64 69 73 6B 20 6F 72 20 -System disk or 7D30 64 69 73 6B 20 65 72 72 6F 72 0D 0A 52 65 70 6C disk error..Repl 7D40 61 63 65 20 61 6E 64 20 73 74 72 69 6B 65 20 61 ace and strike a 7D50 6E 79 20 6B 65 79 20 77 68 65 6E 20 72 65 61 64 ny key when read 7D60 79 0D 0A 00 01 00 02 0D 0A 44 69 73 6B 20 42 6F y........Disk Bo 7D70 6F 74 20 66 61 69 6C 75 72 65 0D 0A 00 ot failure... 0 1 2 3 4 5 6 7 8 9 A B C D E F |
7D7D 4D 69 63 Mic 7D80 72 6F 73 6F 66 74 2C 49 6E 63 20 69 62 6D 62 69 rosoft,Inc ibmbi 7D90 6F 20 20 63 6F 6D 30 69 62 6D 64 6F 73 20 20 63 o com0ibmdos c 7DA0 6F 6D 30 om0 0 1 2 3 4 5 6 7 8 9 A B C D E F |
1[Return to Text] Some 3rd party ROM upgrades, as noted on our Tech Notes page, may allow various MS-DOS versions to access and work with 160 KiB diskettes. Do you have a PC Compatible that can actually copy 160 KiB diskettes? And if so, under which version(s) of DOS?
2[Return to Text] From the perspective of computer forensics or hackers, specifically anyone using DEBUG.COM (or similar utilities), these dual-sided diskettes were very confusing at first, and then required extra effort and time to work with, due to the following decisions made by its developer(s): The Absolute (or Relative) Sector count increases sequentially from 0 to 13Fh (319) for all of the sectors on Side 0 before starting to count any sectors on Side 1; which are Sectors 140h (320) through 27Fh (639). However, the contents of any file which needs to continue from one 8-sector Track to another will alternate from one Side to the other, understandably, to keep the time for moving the drive's heads to a minimum. Yet it was also decided that the Cluster Numbers would directly reference the data no matter where it was written on the diskette. Thus, we have what appears to be some strange facts for these diskettes: The contents, for example, of IBMBIO.COM (1,920 bytes; allocated in four 512-byte sectors) can be found in Clusters 2 and 3 (each cluster is now 1024 bytes each), but those two clusters are on Sectors 142h (322) through 145h (325). Now imagine the extra work needed to view a file using DEBUG, when its contents are spread across many sectors on both sides of a diskette! Note: Pages C-13 through C-19 of the Disk Operating System, Second Edition (May, 1982), Version 1.10, © Copyright International Business Machines Corporation 1981, contain a "Map" (a table) showing the Track, Sector, Side, Relative Sector and Cluster Number for each sector on a dual-sided diskette. This very useful guide to PC DOS can be downloaded as a PDF from: Bit Savers, DOS Version 1.1 Reference. To illustrate the problem, look at where the three DOS System files are located on a 320 KiB diskette:
Name .Ext Size Allocated Clusters Absolute Sectors (Image File Sectors) FAT1/FAT2 1024 - 0 1h (001) - 2h (002) 1 - 2 (Side 0) Directory 3584 - 0 3h (003) - 7h (007) 3 - 7 (Side 0) 0 140h (320) - 141h (321) 8 - 9 (Side 1) IBMBIO COM 1920 2,048 2 - 3 142h (322) - 145h (325) 10 - 13 (Side 1) IBMDOS COM 6400 7,168* 4 146h (326) - 147h (327) 14 - 15 (Side 1) 5 - 8 8h (008) - 00Fh (015) 16 - 23 (Side 0) 9 - 10 148h (328) - 14Bh (331) 24 - 27 (Side 1) COMMAND COM 4959 5,120 11 - 12 14Ch (332) - 14Fh (335) 28 - 29 (Side 1) 13 - 16 10h (016) - 17h (023) 30 - 37 (Side 0) *Allocated space must have an even number of sectors since each cluster is 1024 bytes.
3[Return to Text] For those who'd like more details about these code segments, here's a comparison of the assembly instructions between the end of the final version of LINK.EXE and the code fragment found in the Boot Sector (note: these are not the locations in Memory where the code would be executed!):
Offsets in LINK.EXE (version 1.10) & Code Code from Boot Sector if placed in same locations: --------------------------------------------- -------------------------------------------------- A352 7505 JNZ A359 A352 7505 JNZ A359 A354 C6065730FF MOV BYTE PTR [3057],FF A354 C606772FFF MOV BYTE PTR [2F77],FF A359 837EFC00 CMP WORD PTR [BP-04],+00 A359 837EFC00 CMP WORD PTR [BP-04],+00 A35D 750B JNZ A36A A35D 750B JNZ A36A A35F 807EF73B CMP BYTE PTR [BP-09],3B A35F 807EF73B CMP BYTE PTR [BP-09],3B A363 7505 JNZ A36A A363 7505 JNZ A36A A365 C6065630FF MOV BYTE PTR [3056],FF A365 C606762FFF MOV BYTE PTR [2F76],FF A36A 89EC MOV SP,BP A36A 89EC MOV SP,BP A36C 5D POP BP A36C 5D POP BP A36D CA0400 RETF 0004 A36D CA0400 RETF 0004
As you can see above, after adding the likely missing 75h byte to the beginning of our fragment, the only difference in the code is where two data bytes were located; likely because the earlier code found in the Boot Sector had a shorter total byte count.
4[Return to Text] Although the next file on the IBM PC DOS 1.00 distribution diskette is COMMAND.COM, it does not matter what the next file on the diskette is, since those 2 or 3 sectors copied into Memory are either never used during the boot process; or for COMMAND.COM, not at these Memory locations! (See next Footnote.)
5[Return to Text] The fact that copies of these 2 or 3 sectors from COMMAND.COM are never used by the Boot Process in these Memory locations can easily be proven by formatting a diskette using /S to transfer the system files to it, deleting the COMMAND.COM file (using DEL), copying a number of other files to that diskette, and only then copying COMMAND.COM to that diskette, then, finally, putting that diskette in the A: drive and finding that you can boot-up from it! (So, it does not matter where COMMAND.COM is located on the diskette; only where IBMBIO.COM and IBMDOS.COM are located. THEREFORE, whatever happens to be copied from these 2 or 3 sectors at this point in the boot sequence does not matter; only later on is the code from COMMAND.COM made use of (wherever it happens to be located on the diskette).
6[Return to Text] Thank you Daniel Karlsson for emailing me ("Without the instruction, nothing will be printed by the subroutine.") which called my attention to a broader misconception on my part and a review of the program flow.
First Published: July 29, 2005 (2005.07.29).
Updated: June 10, 2017 (2017.06.10); December 14, 2021 (2021.12.14); big offline update! Added all missing comments, big text revision.
December 20, 2021 (2021.12.20); revisions published, more changes, added footnote. December 24, 2021 (2021.12.24); minor revisions, added another footnote.
December 25, 2021 (2021.12.25); added notes / link to creating a 320 KiB boot diskette. January 1, 2022 (2022.01.01); finished comments for 320 KiB code,
more in footnotes. January 5, 2022 (2022.01.05); added remarks about identifying code at end of FORMAT.COM. January 14, 2022 (2022.01.14); added footnotes 4 and 5.
Last Update: July 27, 2024 (2024.07.27); added footnote 6 after correcting comments.
You can reply to us here.
IBM PC DOS 1.10 Index
MBR
and Boot Records Index
The Starman's Realm Index