Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- [BITS 16]
- [ORG 0x7C00]
- %define GlobalStackSegment 0x9000
- %define GlobalStackTop 0xFFFF
- %define GlobalStage2Start 0x7E00
- %define BootDevice 0x500 ; 0x00 = floppy 1, 0x01 = floppy 2, 0x80 = hdd 1, 0x81 = hdd 2
- %define BootDeviceType 0x501 ; 0 = floppy, 1 = hard drive
- %define SectorCount 0x502 ; the number of sectors on the boot device, starting at 1
- %define HeadCount 0x503 ; the number of heads on the boot device
- %define CylinderCount 0x504 ; the number of cylinders on the boot device
- %define DriveCount 0x506 ; the number of drives on the system
- ; jump to our entry point (and set CS to 0)
- jmp 0x0:main
- ; global variables
- NewLine: db 13, 10, 0
- CaptionMsg: db "iNES Boot Loader v0.1", 13, 10, "Loading... ", 13, 10, 0
- SectorLoadErr: db "Error loading sector.", 13, 10, 0
- WrongDiskErr: db "iNES may only be run from a floppy or hard disk.", 13, 10, 0
- InfoLoadErr: db "Error loading disk information.", 13, 10, 0
- HelloWorld: db "Hello from Sector 2!", 13, 10, 0
- ; entry point
- main:
- ; setup our segment registers
- mov AX, 0
- mov DS, AX
- mov ES, AX
- mov GS, AX
- ; setup our stack
- mov AX, GlobalStackSegment
- mov SS, AX
- mov SP, GlobalStackTop
- ; Display our loading message
- ; copy the ID of the device that loaded this boot sector,
- ; and then determine whether it is a floppy or hard drive.
- mov [BootDevice], DL
- mov DX, 0
- cmp byte [BootDevice], 0x80
- je .setHardDriveType
- cmp byte [BootDevice], 0x81
- je .setHardDriveType
- cmp byte [BootDevice], 0x00
- je .setFloppyDriveType
- cmp byte [BootDevice], 0x01
- je .setFloppyDriveType
- ; an unsupported boot device (non-floppy and non-hard drive)
- ; was used.
- .unsupportedBootDevice:
- push WrongDiskErr
- call PrintString
- call HandleFatalError
- .setHardDriveType:
- mov byte [BootDeviceType], 1
- jmp .continueBoot1
- .setFloppyDriveType:
- mov byte [BootDeviceType], 0
- jmp .continueBoot1
- .continueBoot1:
- ; display the caption
- push CaptionMsg
- call PrintString
- ; now we need to grab boot disk information
- call GetBootDiskInfo
- ; load sector #2
- mov AX, 1
- mov BX, 0x7E00
- call LoadSector
- jmp 0x7E00
- cli
- hlt
- ;; PrintString(const char *str)
- ;; The procedure takes a single WORD argument.
- ;; This procedure is called to display a NULL-terminated string
- ;; to the terminal.
- ;; Controls is returned back to the caller after all charactered are printed.
- ;;
- ;; i.e.
- ;;
- ;; push someString
- ;; call PrintString
- PrintString:
- enter 0, 0
- mov SI, [SS:BP + 4] ; get the first (and only) argument from the stack
- pusha ; save the rest of the registers
- mov AH, 0x0E
- mov BH, 0x00
- mov BL, 0x07
- .printChar:
- lodsb ; load string from SI into AL
- or AL, AL
- jz .endPrintChar
- int 0x10
- jmp .printChar
- .endPrintChar:
- popa ; restore the rest of the registers
- leave
- ret 2
- ;; GetBootDiskInfo()
- ;; Initializes boot disk information such as number of sectors, cylinders, heads, etc.
- ;;
- ;; i.e.
- ;;
- ;; call GetBootDiskInfo
- ;;
- GetBootDiskInfo:
- enter 0, 0
- pusha
- mov AH, 0x08 ; read drive parameters function
- mov DL, [BootDevice]
- int 0x13 ; BIOS interrupt
- jnc .setBootDiskInfo
- ; if clear flag is set, an error occurred
- push InfoLoadErr
- call PrintString
- call HandleFatalError
- ; no error occurred, we can set our boot data
- .setBootDiskInfo:
- mov [DriveCount], DL
- mov [HeadCount], DH
- mov [SectorCount], CL
- and byte [SectorCount], 00111111b
- and CX, 1111111111000000b
- mov [CylinderCount], CX
- popa
- leave
- ret
- ;; LoadSector()
- ;; Loads the given 0-indexed LBA sector into buffer ES:BX.
- ;; AX = sector to load
- ;; ES:BX = buffer to load to
- LoadSector:
- enter 0, 0
- pusha
- ; first we need to convert the given LBA sector into a CHS tuple
- ; C = LBA / (sectors per track * heads per cylinder)
- ; H = (LBA / sectors per track) % heads per cylinder
- ; S = (LBA % sectors per track) + 1
- div byte [SectorCount] ; AX / SectorCount, AL = quotient, AH = remainder
- mov CL, AH ; S = (LBA % sectors per track) + 1
- add CL, 1 ; ^^^
- and CL, 00111111b ; S is only 6 bits.
- mov AH, 0 ; AX = AL
- div byte [HeadCount] ; AX / HeadCount, AL = quotient, AH = remainder
- mov DH, AH ; H = (LBA / sectors per track) % heads per cylinder
- mov AX, 0
- mov AL, byte [SectorCount]
- mul byte [HeadCount] ; AX = AL * HeadCount
- mov DI, AX ; DI = AX
- mov DX, 0
- pop AX ; AX = LBA
- div DI ; LBA / (sectors per track * heads per cylinder), AX = quotient, DX = remainder
- ; C = LBA / (sectors per track * heads per cylinder)
- and AX, 0000001111111111b
- shl AX, 6
- mov CH, 0
- or CX, AX
- ; CL = sector
- ; CH = cylinder
- ; DH = head
- mov DL, [BootDevice]
- mov AL, 1 ; number of sectors to read
- mov AH, 0x02 ; read sector function
- ; ES:BX = buffer
- ; now we can actually read the sector
- mov SI, 0
- .tryLoadSector:
- mov AH, 0x00 ;reset drive
- int 0x13
- mov AH, 0x02
- mov BX, 0x7E00
- int 0x13
- jnc .finishLoadSector
- inc SI
- cmp SI, 5
- je .badFinishLoadSector
- jmp .tryLoadSector
- ; something went wrong
- .badFinishLoadSector:
- push SectorLoadErr
- call PrintString
- mov AL, AH
- add AL, 48
- mov AH, 0x0E
- mov BH, 0x00
- mov BL, 0x07
- int 0x10
- call HandleFatalError
- ; everything is OK!
- .finishLoadSector:
- popa
- leave
- ret
- ;; HandleFatalError()
- ;; This procedure is called when an unrecoverable error occurs.
- ;; Control is NOT handed back to the caller.
- ;;
- ;; i.e.
- ;;
- ;; push errorString
- ;; call PrintString
- ;; call HandleFatalError
- HandleFatalError:
- enter 0, 0
- cli
- hlt
- leave ; <-- this is never called, but put it for consistency
- ret
- ; ----------------------- SIGNATURE --------------------
- times 510-($-$$) db 0
- dw 0xAA55
- push HelloWorld
- call PrintString
- cli
- hlt
- times 1024-($-$$) db 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement