wok diff BootProg/stuff/boot16.asm @ rev 24476

Add some current_version
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Feb 18 09:29:30 2022 +0000 (2022-02-18)
parents
children 04472f031354
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/BootProg/stuff/boot16.asm	Fri Feb 18 09:29:30 2022 +0000
     1.3 @@ -0,0 +1,593 @@
     1.4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     1.5 +;;                                                                          ;;
     1.6 +;;         "BootProg" Loader v 1.5 by Alexey Frunze (c) 2000-2015           ;;
     1.7 +;;                           2-clause BSD license.                          ;;
     1.8 +;;                                                                          ;;
     1.9 +;;                                                                          ;;
    1.10 +;;                              How to Compile:                             ;;
    1.11 +;;                              ~~~~~~~~~~~~~~~                             ;;
    1.12 +;; nasm boot16.asm -f bin -o boot16.bin                                     ;;
    1.13 +;;                                                                          ;;
    1.14 +;;                                                                          ;;
    1.15 +;;                                 Features:                                ;;
    1.16 +;;                                 ~~~~~~~~~                                ;;
    1.17 +;; - FAT12 and FAT16 supported using BIOS int 13h function 42h or 02h.      ;;
    1.18 +;;                                                                          ;;
    1.19 +;; - Loads a 16-bit executable file in the MS-DOS .COM or .EXE format       ;;
    1.20 +;;   from the root directory of a disk and transfers control to it          ;;
    1.21 +;;   (the "ProgramName" variable holds the name of the file to be loaded)   ;;
    1.22 +;;   Its maximum size can be up to 635KB without Extended BIOS Data area.   ;;
    1.23 +;;                                                                          ;;
    1.24 +;; - Prints an error if the file isn't found or couldn't be read            ;;
    1.25 +;;   ("File not found" or "Read error")                                     ;;
    1.26 +;;   and waits for a key to be pressed, then executes the Int 19h           ;;
    1.27 +;;   instruction and lets the BIOS continue bootstrap.                      ;;
    1.28 +;;                                                                          ;;
    1.29 +;; - cpu 8086 is supported                                                  ;;
    1.30 +;;                                                                          ;;
    1.31 +;;                                                                          ;;
    1.32 +;;                             Known Limitations:                           ;;
    1.33 +;;                             ~~~~~~~~~~~~~~~~~~                           ;;
    1.34 +;; - Works only on the 1st MBR partition which must be a PRI DOS partition  ;;
    1.35 +;;   with FAT12 (File System ID: 1) and FAT16 (File System ID: 4, 6)        ;;
    1.36 +;;                                                                          ;;
    1.37 +;;                                                                          ;;
    1.38 +;;                                Known Bugs:                               ;;
    1.39 +;;                                ~~~~~~~~~~~                               ;;
    1.40 +;; - All bugs are fixed as far as I know. The boot sector has been tested   ;;
    1.41 +;;   on the following types of diskettes (FAT12):                           ;;
    1.42 +;;   - 360KB 5"25                                                           ;;
    1.43 +;;   - 1.2MB 5"25                                                           ;;
    1.44 +;;   - 1.44MB 3"5                                                           ;;
    1.45 +;;   on my HDD (FAT16).                                                     ;;
    1.46 +;;                                                                          ;;
    1.47 +;;                                                                          ;;
    1.48 +;;                               Memory Layout:                             ;;
    1.49 +;;                               ~~~~~~~~~~~~~~                             ;;
    1.50 +;; The diagram below shows the typical memory layout. The actual location   ;;
    1.51 +;; of the boot sector and its stack may be lower than A0000H if the BIOS    ;;
    1.52 +;; reserves memory for its Extended BIOS Data Area just below A0000H and    ;;
    1.53 +;; reports less than 640 KB of RAM via its Int 12H function.                ;;
    1.54 +;;                                                                          ;;
    1.55 +;;                                            physical address              ;;
    1.56 +;;                 +------------------------+ 00000H                        ;;
    1.57 +;;                 | Interrupt Vector Table |                               ;;
    1.58 +;;                 +------------------------+ 00400H                        ;;
    1.59 +;;                 |     BIOS Data Area     |                               ;;
    1.60 +;;                 +------------------------+ 00500H                        ;;
    1.61 +;;                 | PrtScr Status / Unused |                               ;;
    1.62 +;;                 +------------------------+ 00600H                        ;;
    1.63 +;;                 |      Loaded Image      |                               ;;
    1.64 +;;                 +------------------------+ nnnnnH                        ;;
    1.65 +;;                 |    Available Memory    |                               ;;
    1.66 +;;                 +------------------------+ A0000H - 512 - 3KB            ;;
    1.67 +;;                 |       Boot Sector      |                               ;;
    1.68 +;;                 +------------------------+ A0000H - 3KB                  ;;
    1.69 +;;                 |     3KB Boot Stack     |                               ;;
    1.70 +;;                 +------------------------+ A0000H                        ;;
    1.71 +;;                 |        Video RAM       |                               ;;
    1.72 +;;                                                                          ;;
    1.73 +;;                                                                          ;;
    1.74 +;;                   Boot Image Startup (register values):                  ;;
    1.75 +;;                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                  ;;
    1.76 +;;  dl = BIOS boot drive number (e.g. 0, 80H)                               ;;
    1.77 +;;  cs:ip = program entry point                                             ;;
    1.78 +;;  ss:sp = program stack (don't confuse with boot sector's stack)          ;;
    1.79 +;;  COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h        ;;
    1.80 +;;  EXE program defaults: ds = es = EXE data - 10h (fake MS-DOS psp),       ;;
    1.81 +;;  ax = 0ffffh (both FCB in the PSP don't have a valid drive identifier),  ;;
    1.82 +;;  cs:ip and ss:sp depends on EXE header                                   ;;
    1.83 +;;  Magic numbers:                                                          ;;
    1.84 +;;    si = 16381 (prime number 2**14-3)                                     ;;
    1.85 +;;    di = 32749 (prime number 2**15-19)                                    ;;
    1.86 +;;    bp = 65521 (prime number 2**16-15)                                    ;;
    1.87 +;;  The magic numbers let the program know whether it has been loaded by    ;;
    1.88 +;;  this boot sector or by MS-DOS, which may be handy for universal, bare-  ;;
    1.89 +;;  metal and MS-DOS programs.                                              ;;
    1.90 +;;                                                                          ;;
    1.91 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.92 +
    1.93 +%define bx(label)       bx+label-boot
    1.94 +
    1.95 +[BITS 16]
    1.96 +[CPU 8086]
    1.97 +
    1.98 +?                       equ     0
    1.99 +ImageLoadSeg            equ     60h
   1.100 +StackSize               equ     3072            ; Stack + cluster list
   1.101 +
   1.102 +[SECTION .text]
   1.103 +[ORG 0]
   1.104 +
   1.105 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.106 +;; Boot sector starts here ;;
   1.107 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.108 +
   1.109 +boot:
   1.110 +        jmp     short   start                   ; MS-DOS/Windows checks for this jump
   1.111 +        nop
   1.112 +bsOemName               DB      "BootProg"      ; 0x03
   1.113 +
   1.114 +;;;;;;;;;;;;;;;;;;;;;
   1.115 +;; BPB starts here ;;
   1.116 +;;;;;;;;;;;;;;;;;;;;;
   1.117 +
   1.118 +bpbBytesPerSector       DW      ?               ; 0x0B
   1.119 +bpbSectorsPerCluster    DB      ?               ; 0x0D
   1.120 +bpbReservedSectors      DW      ?               ; 0x0E
   1.121 +bpbNumberOfFATs         DB      ?               ; 0x10
   1.122 +bpbRootEntries          DW      ?               ; 0x11
   1.123 +bpbTotalSectors         DW      ?               ; 0x13
   1.124 +bpbMedia                DB      ?               ; 0x15
   1.125 +bpbSectorsPerFAT        DW      ?               ; 0x16
   1.126 +bpbSectorsPerTrack      DW      ?               ; 0x18
   1.127 +bpbHeadsPerCylinder     DW      ?               ; 0x1A
   1.128 +bpbHiddenSectors        DD      ?               ; 0x1C
   1.129 +bpbTotalSectorsBig      DD      ?               ; 0x20
   1.130 +
   1.131 +;;;;;;;;;;;;;;;;;;;
   1.132 +;; BPB ends here ;;
   1.133 +;;;;;;;;;;;;;;;;;;;
   1.134 +
   1.135 +bsDriveNumber           DB      ?               ; 0x24
   1.136 +bsUnused                DB      ?               ; 0x25
   1.137 +bsExtBootSignature      DB      ?               ; 0x26
   1.138 +bsSerialNumber          DD      ?               ; 0x27
   1.139 +bsVolumeLabel           DB      "NO NAME    "   ; 0x2B
   1.140 +bsFileSystem            DB      "FAT12   "      ; 0x36
   1.141 +
   1.142 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.143 +;; Boot sector code starts here ;;
   1.144 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.145 +
   1.146 +start:
   1.147 +        cld
   1.148 +
   1.149 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.150 +;; How much RAM is there? ;;
   1.151 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.152 +
   1.153 +        int     12h             ; get conventional memory size (in KBs)
   1.154 +        mov     cx, 106h
   1.155 +        shl     ax, cl          ; and convert it to 16-byte paragraphs
   1.156 +
   1.157 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.158 +;; Reserve memory for the boot sector and its stack ;;
   1.159 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.160 +
   1.161 +        sub     ax, (512+StackSize) /16 ; reserve bytes for the code and the stack
   1.162 +        mov     es, ax                  ; cs:0 = ds:0 = ss:0 -> top - 512 - StackSize
   1.163 +        mov     ss, ax
   1.164 +        mov     sp, 512+StackSize       ; bytes 0-511 are reserved for the boot code
   1.165 +
   1.166 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.167 +;; Copy ourselves to top of memory ;;
   1.168 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.169 +
   1.170 +        mov     si, 7C00h
   1.171 +        xor     di, di
   1.172 +        mov     ds, di
   1.173 +        mov     [si], dx                ; store BIOS boot drive number
   1.174 +        rep     movsw                   ; move 512 bytes (+ 12)
   1.175 +
   1.176 +;;;;;;;;;;;;;;;;;;;;;;
   1.177 +;; Jump to the copy ;;
   1.178 +;;;;;;;;;;;;;;;;;;;;;;
   1.179 +
   1.180 +        push    es
   1.181 +        mov     cl, byte main
   1.182 +        push    cx
   1.183 +        retf
   1.184 +
   1.185 +main:
   1.186 +     %if ImageLoadSeg != main-boot
   1.187 +      %if ImageLoadSeg >= 100h
   1.188 +        mov     cx, ImageLoadSeg
   1.189 +      %else
   1.190 +        mov     cl, ImageLoadSeg
   1.191 +      %endif
   1.192 +     %endif
   1.193 +        push    cx
   1.194 +
   1.195 +;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.196 +;; Get drive parameters ;;
   1.197 +;; Update heads count   ;;
   1.198 +;; for current BIOS     ;;
   1.199 +;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.200 +
   1.201 +        mov     ah, 8
   1.202 +        int     13h                     ; may destroy SI,BP, and DS registers
   1.203 +                                        ; update AX,BL,CX,DX,DI, and ES registers
   1.204 +        push    cs
   1.205 +        pop     ds
   1.206 +        xor     bx, bx
   1.207 +
   1.208 +        and     cx, 3Fh
   1.209 +        cmp     [bx(bpbSectorsPerTrack)], cx
   1.210 +        jne     BadParams               ; verify updated and validity
   1.211 +        mov     al, dh
   1.212 +        inc     ax
   1.213 +        mov     [bpbHeadsPerCylinder], ax
   1.214 +BadParams:
   1.215 +
   1.216 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.217 +;; Load FAT (FAT12: 6KB max, FAT16: 128KB max) ;;
   1.218 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.219 +
   1.220 +        pop     es                      ; ImageLoadSeg
   1.221 +        push    es
   1.222 +
   1.223 +        mul     bx                      ; dx:ax = 0 = LBA (LBA are relative to FAT)
   1.224 +        mov     cx, word [bx(bpbSectorsPerFAT)]
   1.225 +
   1.226 +        call    ReadCXSectors           ; read fat and clear cx
   1.227 +
   1.228 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.229 +;; load the root directory in ;;
   1.230 +;; its entirety (16KB max)    ;;
   1.231 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.232 +
   1.233 +        mov     ax, 32
   1.234 +
   1.235 +        mul     word [bx(bpbRootEntries)]
   1.236 +        div     word [bx(bpbBytesPerSector)]
   1.237 +        xchg    ax, cx                  ; cx = root directory size in sectors, clear ax
   1.238 +
   1.239 +        mov     al, [bpbNumberOfFATs]
   1.240 +        mul     bp                      ; [bx(bpbSectorsPerFAT)], set by ReadCXSectors
   1.241 +
   1.242 +        push    es
   1.243 +        call    ReadCXSectors           ; read root directory, clear cx and di
   1.244 +        pop     es
   1.245 +
   1.246 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.247 +;; Look for the COM/EXE file to load and run ;;
   1.248 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.249 +
   1.250 +                                        ; es:di -> root entries array
   1.251 +
   1.252 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.253 +;; Looks for the file/dir ProgramName    ;;
   1.254 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.255 +;; Input:  ES:DI -> root directory array ;;
   1.256 +;; Output: SI = cluster number           ;;
   1.257 +;;         AX = file sector count        ;;
   1.258 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.259 +
   1.260 +FindNameCycle:
   1.261 +        cmp     byte [es:di], ch
   1.262 +        je      FindNameFailed          ; end of root directory (NULL entry found)
   1.263 +        push    di
   1.264 +        mov     cl, 11
   1.265 +        mov     si, ProgramName         ; ds:si -> program name
   1.266 +        repe    cmpsb
   1.267 +        pop     di
   1.268 +        je      FindNameFound
   1.269 +        add     di, 32
   1.270 +        dec     word [bx(bpbRootEntries)]
   1.271 +        jnz     FindNameCycle           ; next root entry
   1.272 +
   1.273 +FindNameFailed:
   1.274 +        call    Error
   1.275 +        db      "File not found."
   1.276 +
   1.277 +FindNameFound:
   1.278 +        push    si
   1.279 +        mov     si, [es:di+1Ah]         ; si = cluster no.
   1.280 +        les     ax, [es:di+1Ch]         ; file size
   1.281 +        mov     dx, es
   1.282 +        div     word [bx(bpbBytesPerSector)]
   1.283 +        cmp     bx, dx                  ; sector aligned ?
   1.284 +        adc     ax, bx                  ; file last sector
   1.285 +        pop     di                      ; di = ClusterList
   1.286 +
   1.287 +        pop     es                      ; ImageLoadSeg
   1.288 +        push    ax
   1.289 +
   1.290 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.291 +;; build cluster list         ;;
   1.292 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.293 +;; Input:  ES:0 -> FAT        ;;
   1.294 +;;         SI = first cluster ;;
   1.295 +;;         DI = cluster list  :;
   1.296 +;;         CH = 0             ;;
   1.297 +;; Output: SI = cluster list  ;;
   1.298 +;;         CH = 0             ;;
   1.299 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.300 +
   1.301 +        push    di                      ; up to 2 * 635K / BytesPerCluster bytes
   1.302 +        mov     cl, 12
   1.303 +ClusterLoop:
   1.304 +        mov     [di], si
   1.305 +
   1.306 +        mov     ax, es                  ; ax = FAT segment = ImageLoadSeg
   1.307 +        add     si, si                  ; si = cluster * 2
   1.308 +        jnc     First64
   1.309 +        mov     ah, (1000h+ImageLoadSeg)>>8 ; adjust segment for 2nd part of FAT16
   1.310 +First64:
   1.311 +        cmp     [bx(bpbSectorsPerFAT)], cx ; 1..12 = FAT12, 16..256 = FAT16
   1.312 +        mov     ds, ax
   1.313 +        jbe     ReadClusterFat12
   1.314 +
   1.315 +        lodsw                           ; ax = next cluster
   1.316 +        cmp     ax, 0FFF8h
   1.317 +        jmp     ReadClusterDone
   1.318 +
   1.319 +ReadClusterFat12:
   1.320 +        add     si, [cs:di]
   1.321 +        shr     si, 1                   ; si = cluster * 3 / 2
   1.322 +
   1.323 +        lodsw                           ; ax = next cluster
   1.324 +        jnc     ReadClusterEven
   1.325 +
   1.326 +        rol     ax, cl
   1.327 +
   1.328 +ReadClusterEven:
   1.329 +        and     ax, 0FFFh               ; mask cluster value
   1.330 +        cmp     ax, 0FF8h
   1.331 +
   1.332 +ReadClusterDone:
   1.333 +        push    cs
   1.334 +        pop     ds
   1.335 +        inc     di
   1.336 +        inc     di
   1.337 +        xchg    ax, si
   1.338 +        jc      ClusterLoop
   1.339 +        pop     si
   1.340 +        pop     di                      ; file size in sectors
   1.341 +
   1.342 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.343 +;; Load the entire file      ;;
   1.344 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.345 +;; Input:  ES:0 -> buffer    ;;
   1.346 +;;         SI = cluster list ;;
   1.347 +;;         DI = file sectors ;;
   1.348 +;;         CH = 0            ;;
   1.349 +;; Output: BP:0 -> buffer    ;;
   1.350 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.351 +
   1.352 +        push    es
   1.353 +
   1.354 +ReadClusters:
   1.355 +        lodsw
   1.356 +        dec     ax
   1.357 +        dec     ax
   1.358 +
   1.359 +        mov     cl, [bx(bpbSectorsPerCluster)]
   1.360 +        mul     cx                      ; cx = sector count (ch = 0)
   1.361 +
   1.362 +        add     ax, bp                  ; LBA for cluster data
   1.363 +        adc     dx, bx                  ; dx:ax = LBA
   1.364 +
   1.365 +        call    ReadSector              ; clear cx
   1.366 +
   1.367 +        jne     ReadClusters
   1.368 +
   1.369 +        pop     bp                      ; ImageLoadSeg
   1.370 +
   1.371 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.372 +;; Type detection, .COM or .EXE? ;;
   1.373 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.374 +
   1.375 +        mov     ds, bp                  ; bp=ds=seg the file is loaded to
   1.376 +
   1.377 +        add     bp, [bx+08h]            ; bp = image base
   1.378 +        mov     ax, [bx+06h]            ; ax = reloc items
   1.379 +        mov     di, [bx+18h]            ; di = reloc table pointer
   1.380 +
   1.381 +        cmp     word [bx], 5A4Dh        ; "MZ" signature?
   1.382 +        je      RelocateEXE             ; yes, it's an EXE program
   1.383 +
   1.384 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.385 +;; Setup and run a .COM program ;;
   1.386 +;; Set CS=DS=ES=SS SP=0 IP=100h ;;
   1.387 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.388 +
   1.389 +        mov     bp, ImageLoadSeg-10h    ; "org 100h" stuff :)
   1.390 +        mov     ss, bp
   1.391 +        xor     sp, sp
   1.392 +        push    bp                      ; cs, ds and es
   1.393 +        mov     bh, 1                   ; ip
   1.394 +        jmp     short Run
   1.395 +
   1.396 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.397 +;; Relocate, setup and run a .EXE program     ;;
   1.398 +;; Set CS:IP, SS:SP, DS, ES and AX according  ;;
   1.399 +;; to wiki.osdev.org/MZ#Initial_Program_State ;;
   1.400 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.401 +
   1.402 +ReloCycle:
   1.403 +        add     [di+2], bp              ; item seg (abs)
   1.404 +        les     si, [di]                ; si = item ofs, es = item seg
   1.405 +        add     [es:si], bp             ; fixup
   1.406 +        scasw                           ; di += 2
   1.407 +        scasw                           ; point to next entry
   1.408 +
   1.409 +RelocateEXE:
   1.410 +        dec     ax                      ; 32768 max (128KB table)
   1.411 +        jns     ReloCycle               ; leave with ax=0ffffh: both FCB in the
   1.412 +                                        ; PSP don't have a valid drive identifier
   1.413 +        les     si, [bx+0Eh]
   1.414 +        add     si, bp
   1.415 +        mov     ss, si                  ; ss for EXE
   1.416 +        mov     sp, es                  ; sp for EXE
   1.417 +
   1.418 +        lea     si, [bp-10h]            ; ds and es both point to the segment
   1.419 +        push    si                      ; containing the PSP structure
   1.420 +
   1.421 +        add     bp, [bx+16h]            ; cs for EXE
   1.422 +        mov     bx, [bx+14h]            ; ip for EXE
   1.423 +Run:
   1.424 +        pop     ds
   1.425 +        push    bp
   1.426 +        push    bx
   1.427 +        push    ds
   1.428 +        pop     es
   1.429 +
   1.430 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.431 +;; Set the magic numbers so the program knows that it   ;;
   1.432 +;; has been loaded by this bootsector and not by MS-DOS ;;
   1.433 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.434 +        mov     si, 16381 ; prime number 2**14-3
   1.435 +        mov     di, 32749 ; prime number 2**15-19
   1.436 +        mov     bp, 65521 ; prime number 2**16-15
   1.437 +
   1.438 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.439 +;; All done, transfer control to the program now ;;
   1.440 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.441 +        retf
   1.442 +
   1.443 +ReadCXSectors:
   1.444 +        mov     bp, cx
   1.445 +        add     bp, ax                  ; adjust LBA for cluster data
   1.446 +
   1.447 +        mov     di, cx                  ; no file size limit
   1.448 +
   1.449 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.450 +;; Reads sectors using BIOS Int 13h    ;;
   1.451 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.452 +;; Input:  DX:AX = LBA relative to FAT ;;
   1.453 +;;         BX    = 0                   ;;
   1.454 +;;         CX    = sector count        ;;
   1.455 +;;         DI    = file sectors        ;;
   1.456 +;;         ES:BX -> buffer address     ;;
   1.457 +;; Output: ES:BX -> next address       ;;
   1.458 +;;         BX    = 0                   ;;
   1.459 +;;         CX or DI = 0                ;;
   1.460 +;;         DL    = drive number        ;;
   1.461 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.462 +
   1.463 +ReadSector:
   1.464 +        add     ax, [bx(bpbHiddenSectors)]
   1.465 +        adc     dx, [bx(bpbHiddenSectors)+2]
   1.466 +        add     ax, [bx(bpbReservedSectors)]
   1.467 +
   1.468 +        push    si
   1.469 +ReadSectorNext:
   1.470 +        adc     dx, bx
   1.471 +        push    di
   1.472 +        push    cx
   1.473 +
   1.474 +        push    bx
   1.475 +        push    bx
   1.476 +        push    dx      ; 32-bit LBA: up to 2TB
   1.477 +        push    ax
   1.478 +        push    es
   1.479 +        push    bx
   1.480 +        inc     bx      ; sector count word = 1
   1.481 +        push    bx
   1.482 +        dec     bx
   1.483 +        mov     di, 16  ; packet size byte = 16, reserved byte = 0
   1.484 +        push    di
   1.485 +
   1.486 +        xchg    ax, cx                  ; save low LBA
   1.487 +        xchg    ax, dx                  ; get high LBA
   1.488 +        cwd                             ; clear dx (LBA offset <2TB)
   1.489 +        div     word [bx(bpbSectorsPerTrack)] ; up to 8GB disks
   1.490 +
   1.491 +        xchg    ax, cx                  ; restore low LBA, save high LBA / SPT
   1.492 +        div     word [bx(bpbSectorsPerTrack)]
   1.493 +                ; ax = LBA / SPT
   1.494 +                ; dx = LBA % SPT         = sector - 1
   1.495 +        inc     dx
   1.496 +
   1.497 +        xchg    cx, dx                  ; restore high LBA / SPT, save sector no.
   1.498 +        div     word [bx(bpbHeadsPerCylinder)]
   1.499 +                ; ax = (LBA / SPT) / HPC = cylinder
   1.500 +                ; dx = (LBA / SPT) % HPC = head
   1.501 +        mov     ch, al
   1.502 +                ; ch = LSB 0...7 of cylinder no.
   1.503 +        mov     al, 64
   1.504 +        mul     ah
   1.505 +        or      cl, al
   1.506 +                ; cl = MSB 8...9 of cylinder no. + sector no.
   1.507 +        mov     dh, dl
   1.508 +                ; dh = head no.
   1.509 +
   1.510 +ReadSectorRetry:
   1.511 +        mov     dl, [bx]
   1.512 +                ; dl = drive no.
   1.513 +        mov     ah, 42h                 ; ah = 42h = extended read function no.
   1.514 +        mov     si, sp
   1.515 +        int     13h                     ; extended read sectors (DL, DS:SI)
   1.516 +        jnc     ReadSectorNextSegment
   1.517 +
   1.518 +        mov     ax, 201h                ; al = sector count = 1
   1.519 +                                        ; ah = 2 = read function no.
   1.520 +        int     13h                     ; read sectors (AL, CX, DX, ES:BX)
   1.521 +
   1.522 +        jnc     ReadSectorNextSegment
   1.523 +        cbw                             ; ah = 0 = reset function
   1.524 +        int     13h                     ; reset drive (DL)
   1.525 +
   1.526 +        dec     di
   1.527 +        jnz     ReadSectorRetry         ; extra attempt
   1.528 +
   1.529 +        call    Error
   1.530 +        db      "Read error."
   1.531 +
   1.532 +ReadSectorNextSegment:
   1.533 +
   1.534 +        pop     ax                      ; al = 16
   1.535 +        mul     byte [bx(bpbBytesPerSector)+1] ;  = (bpbBytesPerSector/256)*16
   1.536 +        pop     cx                      ; sector count = 1
   1.537 +        pop     bx
   1.538 +        add     [si+6], ax              ; adjust segment for next sector
   1.539 +        pop     es                      ; es:0 updated
   1.540 +        pop     ax
   1.541 +        pop     dx
   1.542 +        pop     di
   1.543 +        pop     di
   1.544 +
   1.545 +        add     ax, cx                  ; adjust LBA for next sector
   1.546 +
   1.547 +        pop     cx                      ; cluster sectors to read
   1.548 +        pop     di                      ; file sectors to read
   1.549 +        dec     di                      ; keep C
   1.550 +        loopne  ReadSectorNext          ; until cluster sector count or file sector count is reached
   1.551 +        pop     si
   1.552 +        mov     dx, [bx]                ; pass the BIOS boot drive to Run or Error
   1.553 +
   1.554 +        ret
   1.555 +
   1.556 +;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.557 +;; Error Messaging Code ;;
   1.558 +;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.559 +
   1.560 +Error:
   1.561 +        pop     si
   1.562 +        mov     ah, 0Eh
   1.563 +        mov     bl, 7
   1.564 +
   1.565 +PutStr:
   1.566 +        lodsb
   1.567 +        int     10h
   1.568 +        cmp     al, "."
   1.569 +        jne     PutStr
   1.570 +
   1.571 +        cbw
   1.572 +        int     16h                     ; wait for a key...
   1.573 +        int     19h                     ; bootstrap
   1.574 +
   1.575 +Stop:
   1.576 +        hlt
   1.577 +        jmp     short Stop
   1.578 +
   1.579 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.580 +;; Fill free space with zeroes ;;
   1.581 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.582 +
   1.583 +                times (512-13-($-$$)) db 0
   1.584 +
   1.585 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.586 +;; Name of the file to load and run ;;
   1.587 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.588 +
   1.589 +ProgramName     db      "STARTUP BIN"   ; name and extension each must be
   1.590 +                                        ; padded with spaces (11 bytes total)
   1.591 +
   1.592 +;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.593 +;; End of the sector ID ;;
   1.594 +;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.595 +
   1.596 +ClusterList     dw      0AA55h          ; BIOS checks for this ID