https://github.com/benwei/bos
以下是bootldr.s
;*********************************************; bootldr.s ; - Bootloader for loading MYOS.BIN;; Modify the source from ; Operating Systems Development Tutorial;*********************************************bits 16 ; we are in 16 bit real modeorg 0 ; we will set regisers laterstart: jmp main ; jump to start of bootloader;*********************************************; BIOS Parameter Block;*********************************************; BPB Begins 3 bytes from start. We do a far jump, which is 3 bytes in size.; If you use a short jump, add a "nop" after it to offset the 3rd byte.bpbOEM db "My OS "bpbBytesPerSector: DW 512bpbSectorsPerCluster: DB 1bpbReservedSectors: DW 1bpbNumberOfFATs: DB 2bpbRootEntries: DW 224bpbTotalSectors: DW 2880bpbMedia: DB 0xf0 ;; 0xF1bpbSectorsPerFAT: DW 9bpbSectorsPerTrack: DW 18bpbHeadsPerCylinder: DW 2bpbHiddenSectors: DD 0bpbTotalSectorsBig: DD 0bsDriveNumber: DB 0bsUnused: DB 0bsExtBootSignature: DB 0x29bsSerialNumber: DD 0xa0a1a2a3bsVolumeLabel: DB "BOS FLOPPY "bsFileSystem: DB "FAT12 ";************************************************;; Prints a string; DS=>SI: 0 terminated string;************************************************;Print:lodsb ; load next byte from string from SI to ALor al, al ; Does AL=0?jz PrintDone ; Yep, null terminator found-bail outmov ah, 0eh ; Nope-Print the characterint 10hjmp Print ; Repeat until null terminator foundPrintDone:ret ; we are done, so returnabsoluteSector db 0x00absoluteHead db 0x00absoluteTrack db 0x00;************************************************;; Convert CHS to LBA; LBA = (cluster - 2) * sectors per cluster;************************************************;ClusterLBA: sub ax, 0x0002 ; zero base cluster number xor cx, cx mov cl, BYTE [bpbSectorsPerCluster] ; convert byte to word mul cx add ax, WORD [datasector] ; base data sector ret;************************************************;; Convert LBA to CHS; AX=>LBA Address to convert;; absolute sector = (logical sector / sectors per track) + 1; absolute head = (logical sector / sectors per track) MOD number of heads; absolute track = logical sector / (sectors per track * number of heads);;************************************************;LBACHS: xor dx, dx ; prepare dx:ax for operation div WORD [bpbSectorsPerTrack] ; calculate inc dl ; adjust for sector 0 mov BYTE [absoluteSector], dl xor dx, dx ; prepare dx:ax for operation div WORD [bpbHeadsPerCylinder] ; calculate mov BYTE [absoluteHead], dl mov BYTE [absoluteTrack], al ret;************************************************;; Reads a series of sectors; CX=>Number of sectors to read; AX=>Starting sector; ES:BX=>Buffer to read to;************************************************;ReadSectors: .MAIN: mov di, 0x0005 ; five retries for error .SECTORLOOP: push ax push bx push cx call LBACHS ; convert starting sector to CHS mov ah, 0x02 ; BIOS read sector mov al, 0x01 ; read one sector mov ch, BYTE [absoluteTrack] ; track mov cl, BYTE [absoluteSector] ; sector mov dh, BYTE [absoluteHead] ; head mov dl, BYTE [bsDriveNumber] ; drive int 0x13 ; invoke BIOS jnc .SUCCESS ; test for read error xor ax, ax ; BIOS reset disk int 0x13 ; invoke BIOS dec di ; decrement error counter pop cx pop bx pop ax jnz .SECTORLOOP ; attempt to read again int 0x18 .SUCCESS: mov si, msgProgress call Print pop cx pop bx pop ax add bx, WORD [bpbBytesPerSector] ; queue next buffer inc ax ; queue next sector loop .MAIN ; read next sector ret;*********************************************; Bootloader Entry Point;*********************************************main: ;---------------------------------------------------- ; code located at 0000:7C00, adjust segment registers ;---------------------------------------------------- cli ; disable interrupts mov ax, 0x07C0 ; setup registers to point to our segment mov ds, ax mov es, ax mov fs, ax mov gs, ax ;---------------------------------------------------- ; create stack ;---------------------------------------------------- mov ax, 0x0000 ; set the stack mov ss, ax mov sp, 0xFFFF sti ; restore interrupts ;---------------------------------------------------- ; Display loading message ;---------------------------------------------------- mov si, msgLoading call Print ;---------------------------------------------------- ; Load root directory table ;---------------------------------------------------- LOAD_ROOT: ; compute size of root directory and store in "cx" xor cx, cx xor dx, dx mov ax, 0x0020 ; 32 byte directory entry mul WORD [bpbRootEntries] ; total size of directory (ax = 0x0020 * 224) div WORD [bpbBytesPerSector] ; sectors used by directory (ax = 0x0020 * 224 / 512) xchg ax, cx ; swap(ax, cx) cx=14 ; compute location of root directory and store in "ax" mov al, BYTE [bpbNumberOfFATs] ; number of FATs (2, ax = 2) mul WORD [bpbSectorsPerFAT] ; sectors used by FATs (9, ax = 18) add ax, WORD [bpbReservedSectors] ; adjust for bootsector(1, ax = 19) mov WORD [datasector], ax ; base of root directory([datasector] = 19) add WORD [datasector], cx ; [datasector] = 19 + 14 = 33 ; read root directory into memory (7C00:0200) mov bx, 0x0200 ; copy root dir above bootcode call ReadSectors ;---------------------------------------------------- ; Find stage 2 ;---------------------------------------------------- ; browse root directory for binary image mov cx, WORD [bpbRootEntries] ; load loop counter mov di, 0x0200 ; locate first root entry .LOOP: push cx mov cx, 0x000B ; eleven character name mov si, ImageName ; image name to find push di rep cmpsb ; test for entry match pop di je LOAD_FAT pop cx add di, 0x0020 ; queue next directory entry loop .LOOP jmp FAILURE ;---------------------------------------------------- ; Load FAT ;---------------------------------------------------- LOAD_FAT: ; save starting cluster of boot image mov dx, WORD [di + 0x001A] mov WORD [cluster], dx ; file first cluster ; compute size of FAT and store in "cx" xor ax, ax mov al, BYTE [bpbNumberOfFATs] ; number of FATs mul WORD [bpbSectorsPerFAT] ; sectors used by FATs mov cx, axmul WORD [bpbBytesPerSector] ; fatsize = sectors used by FATS * bpbBytesPerSector (512)mov WORD [fatsize], ax ; compute location of FAT and store in "ax" mov ax, WORD [bpbReservedSectors] ; adjust for bootsector ; read FAT into memory (7C00:0200) mov bx, 0x0200 ; copy FAT above bootcode call ReadSectors ; read image file into memory (0050:0000) mov ax, 0x0050 mov es, ax ; destination for image mov bx, 0x0000 ; destination for image push bx ;---------------------------------------------------- ; Load Stage 2 ;---------------------------------------------------- LOAD_IMAGE: mov ax, WORD [cluster] ; cluster to read pop bx ; buffer to read into call ClusterLBA ; convert cluster to LBA xor cx, cx mov cl, BYTE [bpbSectorsPerCluster] ; sectors to read call ReadSectors push bx ; compute next cluster mov ax, WORD [cluster] ; identify current cluster mov cx, ax ; copy current cluster mov dx, ax ; copy current cluster shr dx, 0x0001 ; divide by two add cx, dx ; sum for (3/2) mov bx, 0x0200 ; location of FAT in memory add bx, cx ; index into FAT mov dx, WORD [bx] ; read two bytes from FAT test ax, 0x0001 jnz .ODD_CLUSTER .EVEN_CLUSTER: and dx, 0000111111111111b ; take low twelve bits jmp .DONE .ODD_CLUSTER: shr dx, 0x0004 ; take high twelve bits .DONE: mov WORD [cluster], dx ; store new cluster cmp dx, 0x0FF0 ; test for end of file jb LOAD_IMAGE DONE:mov ax, 0x1000mov es, axmov cx, 2 ; read 32 sectorsmov ax, 19 ; starting sectormov bx, 0 ; to 0x10000 call ReadSectors%if 0; backup the FAT ; ESmov cx, word [fatsize]mov si, 0x0200mov ax, 0x1000mov es, axmov di, 0 .loopfatmove:lodsbstosbloop .loopfatmovemov di, 0mov ax, word [fatsize]stosw%endif mov si, msgCRLF call Print push WORD 0x0050 push WORD 0x0000 retf FAILURE: mov si, msgFailure call Print mov ah, 0x00 int 0x16 ; await keypress int 0x19 ; warm boot computer fatsize dw 0x0000 datasector dw 0x0000 cluster dw 0x0000 ImageName db "MYOS BIN" msgLoading db 0x0D, 0x0A, "Loading Boot Image ", 0x00 msgCRLF db 0x0D, 0x0A, 0x00 msgProgress db ".", 0x00 msgFailure db 0x0D, 0x0A, "MISSING OS. Hit Any Key to Reboot", 0x0D, 0x0A, 0x00 TIMES 510-($-$$) DB 0 DW 0xAA55
沒有留言:
張貼留言