Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the forum
Board view  Mix view

I made my own DOS implementation (Announce)

posted by samwdpckr, 17.12.2025, 23:53

IBM PC and compatibles don't check for that "boot sector signature" when booting from a floppy. Some BIOSes check that the first byte on the boot sector is a valid x86 instruction (I remember some sources stating that it is usually done by making sure that its numeral value is larger than 0x30, which also can cause problems because it assumes that the first instruction is a JMP instruction, which it necessarily isn't) but at least the IBM PC and PC XT BIOSes don't seem to have any checks there - it just jumps to the memory address where the contents of the first sector are.

Code from IBM PC BIOS version 3:


;--- INT 19 -----------------------------------------------------
; BOOT STRAP LOADER                                             :
;       IF A 5 1/4" DISKETTE DRIVE IS AVAILABLE ON THE SYSTEM,  :
;       TRACK 0, SECTOR 1 IS READ INTO THE BOOT LOCATION        :
;       (SEGMENT 0, OFFSET 7C00) AND CONTROL IS TRANSFERRED     :
;       THERE.                                                  :
;                                                               :
;       IF THERE IS NO DISKETTE DRIVE, OR IF THERE IS A         :
;       HARDWARE ERROR CONTROL IS TRANSFERRED TO THE RESIDENT   :
;       BASIC ENTRY POINT.                                      :
;                                                               :
; IPL ASSUMPTIONS                                               :
;       8255 PORT 60H BIT 0 = 1 IF IPL FROM DISKETTE            :
;----------------------------------------------------------------
        ASSUME  CS:CODE,DS:ABS0

;----- IPL WAS SUCCESSFUL

H4:
        JMP     BOOT_LOCN
        ORG     0E6F2H
BOOT_STRAP      PROC    NEAR
        STI                             ; ENABLE INTERRUPTS
        SUB     AX,AX
        MOV     DS,AX

;----- RESET DISKETTE PARAMETER TABLE VECTOR

        MOV     WORD PTR DISK_POINTER,OFFSET DISK_BASE
        MOV     WORD PTR DISK_POINTER+2,CS
        MOV     AX,DATA_WORD[OFFSET EQUIP_FLAG] ; GET THE EQUIPMENT SWITCHES
        TEST    AL,1                    ; ISOLATE IPL SENSE SWITCH
        JZ      H3                      ; GO TO CASSETTE BASIC ENTRY POINT

;----- MUST LOAD SYSTEM FROM DISKETTE -- CX HAS RETRY COUNT

        MOV     CX,4                    ; SET RETRY COUNT
H1:                                     ; IPL_SYSTEM
        PUSH    CX                      ; SAVE RETRY COUNT
        MOV     AH,0                    ; RESET THE DISKETTE SYSTEM
        INT     13H                     ; DISKETTE_IO
        JC      H2                      ; IF ERROR, TRY AGAIN
        MOV     AX,201H                 ; READ IN THE SINGLE SECTOR
        SUB     DX,DX
        MOV     ES,DX
        MOV     BX,OFFSET BOOT_LOCN
        MOV     CX,1                    ; SECTOR 1, TRACK 0
        INT     13H                     ; DISKETTE_IO
H2:     POP     CX                      ; RECOVER RETRY COUNT
        JNC     H4                      ; CF SET BY UNSUCCESSFUL READ
        LOOP    H1                      ; DO IT FOR RETRY TIMES

;------ UNABLE TO IPL FROM THE DISKETTE

H3:                                     ; CASSETTE_JUMP:
        INT     18H                     ; USE INTERRUPT VECTOR TO GET TO BASIC
BOOT_STRAP      ENDP


And BOOT_LOCN is 0x7C00.

In the PC XT BIOS the code is just arranged little differently, but it is still basically the same:


;--- INT 19 ---------------------------------------------
; BOOT STRAP LOADER                                     :
;       TRACK 0, SECTOR 1 IS READ INTO THE              :
;       BOOT LOCATION (SEGMENT 0, OFFSET 7C00)          :
;       AND CONTROL IS TRANSFERRED THERE.               :
;                                                       :
;       IF THERE IS A HARDWARE ERROR CONTROL IS         :
;       TRANSFERRED TO THE ROM BASIC ENTRY POINT.       :
;--------------------------------------------------------
        ASSUME  CS:CODE,DS:ABS0
        ORG     0E6F2H

BOOT_STRAP      PROC    NEAR
        STI                             ; ENABLE INTERRUPTS
        SUB     AX,AX                   ; ESTABLISH ADDRESSING
        MOV     DS,AX

;----- RESET DISKETTE PARAMETER TABLE VECTOR

        MOV     WORD PTR DISK_POINTER,OFFSET DISK_BASE
        MOV     WORD PTR DISK_POINTER+2,CS

;----- LOAD SYSTEM FROM DISKETTE -- CX HAS RETRY COUNT

        MOV     CX,4                    ; SET RETRY COUNT
H1:                                     ; IPL_SYSTEM
        PUSH    CX                      ; SAVE RETRY COUNT
        MOV     AH,0                    ; RESET THE DISKETTE SYSTEM
        INT     13H                     ; DISKETTE_IO
        JC      H2                      ; IF ERROR, TRY AGAIN
        MOV     AX,201H                 ; READ IN THE SINGLE SECTOR
        SUB     DX,DX
        MOV     ES,DX
        MOV     BX,OFFSET BOOT_LOCN
                                        ; DRIVE 0, HEAD 0
        MOV     CX,1                    ; SECTOR 1, TRACK 0
        INT     13H                     ; DISKETTE_IO
H2:
        POP     CX                      ; RECOVER RETRY COUNT
        JNC     H4                      ; CF SET BY UNSUCCESSFUL READ
        LOOP    H1                      ; DO IT FOR RETRY TIMES

;------ UNABLE TO IPL FROM THE DISKETTE

H3:
        INT     18H                     ; GO TO RESIDENT BASIC

;----- IPL WAS SUCCESSFUL

H4:
        JMP     BOOT_LOCN
BOOT_STRAP      ENDP


The PC AT BIOS does a lot more than PC and XT BIOSes. With floppies it first checks that the first word is not zero, and then it checks that the first 10 words are not the same. Technically this could also lead into problems if the first instruction is a short jump to somewhere beyond the first 20 bytes and the next 18 bytes are unreachable "code" that also happens to be the same JMP instruction repeating itself, in which case the system refuses to boot from a diskette that maybe should be bootable.

With hard disks the AT BIOS only checks that the boot sector signature 0x55AA is there. No other checks are made.

Code from IBM PC AT BIOS:


;--- BOOT_STRAP -- INT  19H ---------------------------
; BOOT STRAP LOADER                                   :
;       TRACK 0, SECTOR 1 IS READ INTO THE            :
;       BOOT LOCATION (SEGMENT 0 OFFSET 7C00)         :
;       AND CONTROL IS TRANSFERRED THERE.             :
;                                                     :
;       IF THERE IS A HARDWARE ERROR CONTROL IS       :
;       TRANSFERRED TO THE ROM BASIC ENTRY POINT      :
;------------------------------------------------------
        ASSUME CS:CODE,DS:ABS0

BOOT_STRAP_1    PROC    NEAR

        SUB     AX,AX                   ; ESTABLISH ADDRESSING
        MOV     DS,AX

;------ RESET THE DISK PARAMETER TABLE VECTOR

        MOV     WORD PTR DISK_POINTER, OFFSET DISK_BASE
        MOV     WORD PTR DISK_POINTER+2,CS

;------ CLEAR BOOT_LOCN

        MOV     CX,256                  ; CLEAR 256 WORDS
        MOV     BX,OFFSET BOOT_LOCN
H0:     MOV     [BX],AX
        ADD     BX,2
        LOOP    H0

;------ LOAD SYSTEM FROM DISKETTE -- CX HAS RETRY COUNT

        STI
        MOV     CX,4                    ; SET RETRY COUNT
H1:     PUSH    CX                      ; IPL SYSTEM
        MOV     AH,0                    ; RESET THE DISKETTE SYSTEM
        INT     13H                     ; DISKETTE_IO
        JC      H2                      ; IF ERROR, TRY AGAIN

        MOV     AX,201H                 ; READ IN THE SINGLE SECTOR
        SUB     DX,DX                   ; TO THE BOOT LOCATION
        MOV     ES,DX
        MOV     BX,OFFSET BOOT_LOCN     ; DRIVE 0, HEAD 0
        MOV     CX,1                    ; SECTOR 1, TRACK 0
        INT     13H                     ; DISKETTE_IO
H2:     POP     CX                      ; RECOVER RETRY COUNT
        JNC     H4                      ; CARRY FLAG SET BY UNSUCCESSFUL READ
        CMP     AH,80H                  ; IF TIME OUT, NO RETRY
        JZ      H5                      ; TRY FIXED DISK
        LOOP    H1                      ; DO IT FOR RETRY TIMES
        JMP     H5                      ; TRY FIXED DISK

;------ BOOT RECORD READ SUCCESSFUL
;------ INSURE FIRST BYTE OF LOADED BOOT RECORD IS VALID (NOT ZERO)

H4:     CMP     WORD PTR BOOT_LOCN,00H  ; CHECK FOR FIRST INSTRUCTION INVALID
        JE      H10                     ; IF BOOT NOT VALID PRINT MESSAGE HALT

;------ INSURE DATA PATTERN FIRST 10 WORDS NOT ALL EQUAL

        MOV     DI,OFFSET BOOT_LOCN     ; CHECK DATA PATTERN
        MOV     CX,10                   ; CHECK THE NEXT 10 WORDS
        MOV     AX,WORD PTR BOOT_LOCN

H4A:    ADD     DI,2                    ; POINT TO NEXT LOCATION
        CMP     AX,[DI]                 ; CHECK DATA PATTERN FOR A FILL PATTERN
        LOOPZ   H4A
        JZ      H10                     ; BOOT NOT VALID PRINT MESSAGE HALT

H4_A:   JMP     BOOT_LOCN

;------ ATTEMPT BOOTSTRAP FROM FIXED DISK

H5:     MOV     AL,044H                 ; <><><><><><><><><><><><><>
        OUT     MFG_PORT,AL             ; <><><>CHECKPOINT 44 <><><>
        ASSUME  DS:DATA
        CALL    DDS
        TEST    HF_CNTRL,DUAL           ; FLOPPY/FIXED DISK CARD INSTALLED
        ASSUME  DS:ABS0
        MOV     AX,ABS0                 ; ESTABLISH ADDRESSING
        MOV     DS,AX
        JZ      H9                      ; GO IF NOT

;------ CHECK FOR FIXED DISK INITIALIZATION ERROR

        MOV     AL,DIAG_STATUS          ; GET POST POWER ON STATUS (NMI ENABLED)
        AND     AL,07FH
        OUT     CADR_PRT,AL
        JMP     SHORT $+2
        IN      AL,CDATA_PRT
        TEST    AL,HF_FAIL              ; DID WE HAVE A FIXED DISK FAILURE?
        JNZ     H9                      ; GO IF YES

        SUB     AX,AX                   ; RESET DISKETTE
        SUB     DX,DX
        INT     13H
        MOV     CX,3                    ; RETRY COUNT
H6:
        PUSH    CX                      ; SAVE RETRY COUNT
        MOV     DX,0080H                ; FIXED DISK ZERO
        MOV     AX,0201H                ; READ IN A SINGLE SECTOR
        SUB     BX,BX
        MOV     ES,BX
        MOV     BX,OFFSET BOOT_LOCN     ; TO THE BOOT LOCATION
        MOV     CX,1                    ; SECTOR 1, TRACK 0
        INT     13H                     ; FILE I/O CALL
        POP     CX                      ; RECOVER RETRY COUNT
        JC      H8
        CMP     WORD PTR BOOT_LOCN+510D,0AA55H ; TEST FOR GENERIC BOOT BLOCK
        JZ      H4_A

H8:     PUSH    CX
        MOV     DX,0080H                ; FIXED DISK ZERO
        SUB     AX,AX                   ; RESET THE FIXED DISK
        INT     13H                     ; FILE I/O CALL
        POP     CX                      ; RESTORE LOOP COUNT
        JC      H10A                    ; IF ERROR, TRY AGAIN
        LOOP    H6                      ; DO IT FOR RETRY TIMES

;------ UNABLE TO IPL FROM THE DISKETTE OR FIXED DISK

H9:     MOV     AL,045H                 ; <><><><><><><><><><><><><>
        OUT     MFG_PORT,AL             ; <><><>CHECKPOINT 45 <><><>

        INT     18H                     ; GO TO RESIDENT BASIC

;------ HARD FILE RESET FAILURE

H10A:   LOOP    H8                      ; TRY RESET AGAIN
        JMP     H9                      ; GO TO RESIDENT BASIC

;------ IF DISKETTE READ OK BUT BOOT RECORD IS NOT STOP SYSTEM ALLOW SOFT RESET

H10:    MOV     SI,OFFSET BOOT_INVA     ; PRINT DISKETTE BOOT
        CALL    E_MSG                   ; PRINT MESSAGE
H11:    JMP     H11
BOOT_STRAP_1    ENDP

 

Complete thread:

Back to the forum
Board view  Mix view
23155 Postings in 2179 Threads, 404 registered users (0 online)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum