added some code to read from disk
This commit is contained in:
+126
-3
@@ -71,16 +71,139 @@ main:
|
|||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov sp, 0x7c00 ; stack will grow downwards in memory as it is filled
|
mov sp, 0x7c00 ; stack will grow downwards in memory as it is filled
|
||||||
|
|
||||||
|
;; read something from floppy disk
|
||||||
|
;; BIOS should have placed drive number in dl
|
||||||
|
mov [ebr_drive_number], dl
|
||||||
|
mov ax, 1 ; LBA=1 start reading at first sector after bootloader
|
||||||
|
mov cl, 1 ; read 1 sector
|
||||||
|
mov bx, 0x7E00 ; data should be read into memory after the bootloader
|
||||||
|
call disk_read
|
||||||
|
|
||||||
;; print message
|
;; print message
|
||||||
mov si, msg_hello
|
mov si, msg_hello
|
||||||
call puts
|
call puts
|
||||||
|
|
||||||
hlt ; stop executing
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
floppy_error:
|
||||||
|
mov si, msg_read_failed
|
||||||
|
call puts
|
||||||
|
jmp wait_key_and_reboot
|
||||||
|
|
||||||
|
wait_key_and_reboot:
|
||||||
|
mov ah, 0
|
||||||
|
int 16h ; wait for keypress
|
||||||
|
jmp 0FFFFh:0 ; jump to begininng of BIOS
|
||||||
|
|
||||||
.halt:
|
.halt:
|
||||||
jmp .halt ; really make sure we're not executing random shit
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Disk Routines
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; Convert an LBA address to a CHS address
|
||||||
|
;; Parameters:
|
||||||
|
;; - ax: LBA Address
|
||||||
|
;;
|
||||||
|
;; Returns:
|
||||||
|
;; - cx[bits 0-5]: sector number
|
||||||
|
;; - cx[bits 6-15]: cylinder
|
||||||
|
;; - dh: head
|
||||||
|
;;
|
||||||
|
lba_to_chs:
|
||||||
|
push ax
|
||||||
|
push dx
|
||||||
|
|
||||||
msg_hello: db 'Hello Shitass!', ENDL, 0 ; named constant
|
; Calculate Sector
|
||||||
|
; div dvides whatever is in ax by the divisor supplied
|
||||||
|
; ax contains our desired LBA at this point
|
||||||
|
xor dx, dx ; dx = 0 (dx receives the remainder after a div instruction)
|
||||||
|
div word [bdb_sectors_per_track] ; ax = LBA / sectors_per_track
|
||||||
|
; dx = LBA % sectors_per_track
|
||||||
|
inc dx ; dx = dx + 1 (this is the sector value)
|
||||||
|
mov cx, dx ; put sector value into cx
|
||||||
|
|
||||||
|
; Calculate Cylinder/Head
|
||||||
|
; ax still contains (LBA / sectors_per_track) at this point
|
||||||
|
xor dx, dx ; dx = 0
|
||||||
|
div word [bdb_heads] ; ax = (LBA / sectors_per_track) / heads (this is the cylinder value)
|
||||||
|
; dx = (LBA / sectors_per_track) % heads (this is the head value)
|
||||||
|
|
||||||
|
;; Move calculated values to target registers (cx already contains sector number by now)
|
||||||
|
mov dh, dl ; dl is the lower 8 bits of dx, this moves the calculated head value to dh
|
||||||
|
mov ch, al ; ch = cylinder (lower 8 bits)
|
||||||
|
shl ah, 6
|
||||||
|
or cl, ah ; put upper 2 bits of cylinder in CL
|
||||||
|
|
||||||
|
pop ax
|
||||||
|
mov dl, al ; restore whatever was in dl prior to this. dh needs to have the calculated head value
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Reads sectors from a disk into memory
|
||||||
|
;; Parameters:
|
||||||
|
;; - ax: LBA Address
|
||||||
|
;; - cl: number of sectors to read (128 max)
|
||||||
|
;; - dl: drive number
|
||||||
|
;; - es:bx: memory address where to store data
|
||||||
|
disk_read:
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push di
|
||||||
|
|
||||||
|
push cx ; save number of sectors to read to stack (lba_to_chs uses cx)
|
||||||
|
call lba_to_chs ; calculate CHS
|
||||||
|
pop ax ; restore number of sectors to read into ax, cx contains sector and cylinder, dh contains head
|
||||||
|
mov ah, 02h ; this is required by interrupt 13
|
||||||
|
mov di, 3 ; retry count
|
||||||
|
|
||||||
|
.retry:
|
||||||
|
pusha ; save all registers, BIOS does what BIOS wants
|
||||||
|
stc ; explicitly set carry flag to be safe
|
||||||
|
int 13h ; carry flag cleared = success
|
||||||
|
jnc .done ; jumo if carry not set
|
||||||
|
|
||||||
|
; read failed
|
||||||
|
popa
|
||||||
|
call disk_reset
|
||||||
|
|
||||||
|
dec di
|
||||||
|
test di, di
|
||||||
|
jnz .retry
|
||||||
|
|
||||||
|
.fail:
|
||||||
|
; all retry attempts used
|
||||||
|
jmp floppy_error
|
||||||
|
|
||||||
|
.done:
|
||||||
|
popa
|
||||||
|
|
||||||
|
pop di
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Resets disk controller
|
||||||
|
;; Parameters:
|
||||||
|
;; - dl: drive number
|
||||||
|
disk_reset:
|
||||||
|
pusha
|
||||||
|
mov ah, 0
|
||||||
|
stc
|
||||||
|
int 13h
|
||||||
|
jc floppy_error
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
msg_hello: db 'Hello Shitass!', ENDL, 0 ; named constant
|
||||||
|
msg_read_failed: db 'Read from disk failed!', ENDL, 0
|
||||||
|
|
||||||
times 510-($-$$) db 0 ; pad program with zeros up to byte 510
|
times 510-($-$$) db 0 ; pad program with zeros up to byte 510
|
||||||
dw 0AA55h ; BIOS requires last two bytes of first sector to be AA55
|
dw 0AA55h ; BIOS requires last two bytes of first sector to be AA55
|
||||||
|
|||||||
Reference in New Issue
Block a user