maa@nbires.nbi.com (Mark Armbrust) (06/09/89)
There is a bug in MS-DOS 3.30 that causes the INTR 25/26 Absolute Disk I/O functions to trash memory if they are issued for invalid drive numbers. I have not checked any other version of DOS to see if they also have the bug. What happens is that if the drive number in AL refers to an invalid drive, MS-DOS writes a word of 0FFFFh at ES:[BP+1Eh]. There are two ways to get around the problem; one is to make sure that you never call INTR 25/26 with invalid drive numbers or that you set ES:BP to point to a buffer that you don't mind having trashed (can be the read buffer since the bug occurs before the actual read operation). The other is to patch MS-DOS to fix the problem. What follows it a patch for MS-DOS 3.30's MSDOS.SYS file to fix the bug. This has not been checked on any other version of DOS and will most likely NOT work on any version of DOS other than MS-DOS 3.30. FC /B MSDOS.MS MSDOS.SYS +------- MS-DOS 3.30 MSDOS.SYS | +---- Patched MSDOS.SYS | | 000015AD: 26 1F 000015AE: C7 73 000015AF: 46 01 000015B0: 1E C3 000015B1: FF 26 000015B2: FF C7 000015B3: 1F 46 000015B4: 73 1E 000015B5: 01 FF 000015B6: C3 FF 000015D3: E2 DC For those of you who want to know what you are changing: ABSSETUP: INC BYTE PTR SS:INDOS ;15A0 36 FE 06 CF 02 STI ;15A5 FB CLD ;15A6 FC PUSH DS ;15A7 1E PUSH SS ;15A8 16 POP DS ;15A9 1F CALL GETBP ;15AA E8 8D 00 GETBP routine sets up ES and BP to point to an internal data structure ONLY if the drive number in AL is valid. It returns with carry set if the drive number is not valid and ES and BP are unchanged. MOV WORD PTR ES:[BP+1EH],0FFFF ;15AD 26 C7 46 1E FF FF POP DS ;15B3 1F JNB L15B7 ;15B4 73 01 ;L15B6 L15D2 CJ L15B6: RET_NEAR ;15B6 C3 The fix is to move the MOV instruction above down to here so that is is only executed for valid drive numbers. ;L15B7 L15B4 CJ L15B7: PUSH DS ;15B7 1E PUSH SI ;15B8 56 PUSH AX ;15B9 50 PUSH SS ;15BA 16 POP DS ;15BB 1F MOV SI,OFFSET OPENBUF ;15BC BE 60 03 MOV [SI],AL ;15BF 88 04 ADD BYTE PTR [SI],41H ;'A' ;15C1 80 04 41 MOV WORD PTR [SI+1],OFFSET L003A ;15C4 C7 44 01 3A 00 MOV AX,OFFSET DAYCNT ;15C9 B8 00 03 CLC ;15CC F8 INT 2AH ;15CD CD 2A POP AX ;15CF 58 POP SI ;15D0 5E POP DS ;15D1 1F JNB L15B6 ;15D2 73 E2 note that the target of this jump moves because of the code patch. MOV WORD PTR SS:EXTERR,OFFSET BCON ;15D4 36 C7 06 D2 02 32 00 ;L15DB L1643 CJ L15DB: RET_NEAR ;15DB C3 This is the entry print for INTR 25H ;L15DC L73D9 DI ABSDRD: CLI ;15DC FA MOV CS:USER_SS,SS ;15DD 2E 8C 16 20 05 MOV CS:USER_SP,SP ;15E2 2E 89 26 1E 05 PUSH CS ;15E7 0E POP SS ;15E8 17 MOV SP,OFFSET DSKSTACK ;15E9 BC 86 08 PUSH ES ;15EC 06 CALL ABSSETUP ;15ED E8 B0 FF JB L160C ;15F0 72 1A CALL DSKREAD ;15F2 E8 B1 2A ;L15F5 L1638 CJ L15F5: JZ L160C ;15F5 74 15 PUSH ES ;15F7 06 PUSH CS ;15F8 0E POP ES ;15F9 07 XOR AH,AH ;15FA 32 E4 MOV CX,OFFSET L0006 ;15FC B9 06 00 MOV DI,OFFSET MSC001S ;15FF BF 89 0F REPNZ SCASB ;1602 F2 AE JNZ L160A ;1604 75 04 MOV AH,ES:[DI+5] ;1606 26 8A 65 05 ;L160A L1604 CJ L160A: POP ES ;160A 07 STC ;160B F9 ;L160C L15F0 CJ L15F5 CJ L1633 CJ L160C: POP ES ;160C 07 CLI ;160D FA DEC BYTE PTR SS:INDOS ;160E 36 FE 0E CF 02 MOV SS,SS:USER_SS ;1613 36 8E 16 20 05 MOV SP,CS:USER_SP ;1618 2E 8B 26 1E 05 STI ;161D FB RET_FAR ;161E CB Mark Armbrust maa@nbires.nbi.com maa@nbires.UUCP -- Mark Armbrust maa@nbires.nbi.com maa@nbires.UUCP
maa@nbires.nbi.com (Mark Armbrust) (06/10/89)
In article <410@nbires.nbi.com> maa@nbires.nbi.com (Mark Armbrust) writes: > >There is a bug in MS-DOS 3.30 that causes the INTR 25/26 Absolute Disk I/O >functions to trash memory if they are issued for invalid drive numbers. >I have not checked any other version of DOS to see if they also have the >bug. > >What happens is that if the drive number in AL refers to an invalid drive, >MS-DOS writes a word of 0FFFFh at ES:[BP+1Eh]. I did a bit of looking at various version of DOS that we have around here and the bug seems to have been introduced in MS/PC-DOS 3.1; it has been fixed in MS-DOS 4.0 (I didn't check PC-DOS 4.0). It seems that the easiest way to deal with this problem is to set ES to 0F000h. This makes DOS do the erroneous write into the ROM. For example, from DF.C where I first found the problem: int DriveReady (int drive, char *buffer) { union REGS regs; + struct SREGS sregs; + segread (&sregs); + sregs.es = 0xF000; regs.h.al = (unsigned char) drive; regs.x.bx = (int) buffer; regs.x.cx = 1; regs.x.dx = 0; - int86 (0x25, ®s, ®s); + int86x (0x25, ®s, ®s, &sregs); return ! (regs.x.cflag); } >This is the entry print for INTR 25H ^^^^^ POINT! My fingers sometimes have a life of their own. 8-( -- Mark Armbrust maa@nbires.nbi.com maa@nbires.UUCP