Code: Select all
; DX = 10-bit cylinder number (zero based)
; AL = 6-bit sector number (1 based)
mov ch,dl
mov cl,dh
shl cl,6
and al,3Fh
or cl,al
; CX now is 10-bit cylinder number in CHS form (zero based)
Code: Select all
; DX = 10-bit cylinder number (zero based)
; AL = 6-bit sector number (1 based)
mov ch,dl
mov cl,dh
shl cl,6
and al,3Fh
or cl,al
; CX now is 10-bit cylinder number in CHS form (zero based)
This is one of those "catch 22" things. By anding AL with 0x3F, I am making sure that if AL > 63, I am not "adding" to the cylinder value. However, if AL > 63, I messed up somewhere else already and it is a wonder I got this far.Armature wrote:and I was wondering why your anding the value of AL with 0x3F. Doesn't this just make the value in AL the same as it was before the and operation?
Code: Select all
LBAToCHS: ;AX = LBA
div [bpbSectorsPerTrack] ;AX = LBA/SPT, DX = AbsoluteSector - 1
push dx ;Store sector on stack
div [bpbHeadsPerCylinder] ;AX = Cylinder, DX = head
pop bx ;store the sector into BX from stack
inc bx ;BX = Sector
mov ch, bl ;Lower 8 bits [First 8 bits of the cylinder] into the upper 8 bits of CH
mov cl, bh ;Upper 8 bits [Last 2 bits of the cylinder located here]
shl bl, 6 ;move the bits over by six so 00000011 would look like 11000000
or cl, al ;CX should now be a proper 10 bit cylinder and 6 bit sector with dl as the head
mov dh, 0x00
xchg dh, dl
Code: Select all
org 0x7C00 ;1)
jmp short Boot ;2)
nop ;3)
;4)
bpbOEM db "AAAAAAAA" ;5) OEM label for the disk (8 bytes)
bpbBytesPerSector: DW 512 ;6) The size of the sectors in bytes
bpbSectorsPerCluster: DB 1 ;7) How many sectors make up a cluster
bpbReservedSectors: DW 1 ;How many sectors are being reserved (only one: the boot sector)
bpbNumberOfFATs: DB 2 ;How many FAT tables exist (The oringal and a backup)
bpbRootEntries: DW 224 ;How many files can be stored in the root directory
bpbTotalSectors: DW 2880 ;How many sectors exist on this disk
bpbMedia: DB 0xf0 ;The type of media
bpbSectorsPerFAT: DW 9 ;how many sectors the FAT table takes up on disk
bpbSectorsPerTrack: DW 18 ;how many sectors fit on one track
bpbHeadsPerCylinder: DW 2 ;how many physical heads
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "AAAAAAAAAAA"
bsFileSystem: DB "FAT12 "
Boot:
cli
mov ax, 0x0000
mov es, ax
mov ds, ax
mov ss, ax
mov sp, 0x7C00
mov bp, 0x0500
sti
call ResetDisk
FindRootDir:
mov ax, 0x0000
mov ax, word [bpbSectorsPerFAT]
mov bx, word [bpbNumberOfFATs]
mul bx
add ax, 1 ;AX is now the starting sector of the root directory in LBA
jmp LBAToCHS ;we now need to convert this into the CHS format
ReadFAT:
mov di, [0x7E00]
mov si, [KERNEL]
cmp si, di
jne _NotFound
inc si
inc di
dec cx
cmp cx, 0x0000
je _LoadEntry
jne ReadFAT
_LoadEntry:
mov si, KERF
call BPrint
cli
hlt
_NotFound:
mov si, KERNF
call BPrint
cli
hlt
BPrint:
mov ah, 0x0E
_BPrintLoop:
lodsb
cmp al, 0
je _BDone
int 0x10
jmp _BPrintLoop
_BDone:
ret
ResetDisk:
pusha
mov ah, 0x00
mov dl, 0x00
int 0x13
jc DiskError
popa
ret
ReadDisk:
pusha
mov si, READING
call BPrint
popa
mov ah, 0x02
mov bx, 0x7E00 ;ES:BX 0x0000:0x7E00
int 0x13
jc DiskError
mov cx, 0x0008
jmp ReadFAT
DiskError:
mov si, DISKERR
call BPrint
cli
hlt
LBAToCHS: ;AX = LBA
div word [bpbSectorsPerTrack] ;AX = LBA/SPT, DX = AbsoluteSector - 1
push dx ;Store sector on stack
div word [bpbHeadsPerCylinder] ;AX = Cylinder, DX = head
pop bx ;store the sector into BX from stack
inc bx ;BX = Sector
mov ch, bl ;Lower 8 bits [First 8 bits of the cylinder] into the upper 8 bits of CH
mov cl, bh ;Upper 8 bits [Last 2 bits of the cylinder located here]
shl cl, 6 ;move the bits over by six so 00000011 would look like 11000000
or cl, al ;CX should now be a proper 10 bit cylinder and 6 bit sector with dl as the head
mov dh, 0x00 ;Zero out the DH register
xchg dh, dl ;Move the head value into the DH register and zero out the DL register
jmp ReadDisk ;Read The disk with the current register values
READING db 'Reading Disk...', 0x0A, 0x0D, 0
DISKERR db '!!ATTENTION!! - Disk Error. The system has been halted to prevent damage.', 0x0A, 0x0D, 0
KERNF db '!!ATTENTION!! - No Kernel [TerSysVI.bin] found. The system has been halted to prevent damage.', 0x0A, 0x0D, 0
KERNEL db 'TerSysVI BIN'
KERF db 'Kernel found. Loading Kernel from disk...', 0x0A, 0x0D, 0
times 510 - ($-$$) db 0
dw 0xAA55
Code: Select all
...
bpbNumberOfFATs: DB 2 ;How many FAT tables exist (The oringal and a backup)
bpbRootEntries: DW 224 ;How many files can be stored in the root directory
...
bpbSectorsPerFAT: DW 9 ;how many sectors the FAT table takes up on disk
bpbSectorsPerTrack: DW 18 ;how many sectors fit on one track
...
FindRootDir:
mov ax, 0x0000
mov ax, word [bpbSectorsPerFAT]
mov bx, word [bpbNumberOfFATs]
Code: Select all
mov bx, word [bpbNumberOfFATs]
Code: Select all
org 0x7C00 ;1)
jmp short Boot ;2)
nop ;3)
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ;4)
bpbOEM db "AAAAAAAA" ;5) OEM label for the disk (8 bytes)
bpbBytesPerSector: DW 512 ;6) The size of the sectors in bytes
bpbSectorsPerCluster: DB 1 ;7) How many sectors make up a cluster
bpbReservedSectors: DW 1 ;How many sectors are being reserved (only one: the boot sector)
bpbNumberOfFATs: DB 2 ;How many FAT tables exist (The oringal and a backup)
bpbRootEntries: DW 224 ;How many files can be stored in the root directory
bpbTotalSectors: DW 2880 ;How many sectors exist on this disk
bpbMedia: DB 0xf0 ;The type of media
bpbSectorsPerFAT: DW 9 ;how many sectors the FAT table takes up on disk
bpbSectorsPerTrack: DW 18 ;how many sectors fit on one track
bpbHeadsPerCylinder: DW 2 ;how many physical heads
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "AAAAAAAAAAA"
bsFileSystem: DB "FAT12 "
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Boot:
cli
mov ax, 0x0000
mov es, ax
mov ds, ax
mov ss, ax
mov sp, 0x7C00
mov bp, 0x0500
sti
call ResetDisk
FindRootDir:
mov ax, word [bpbSectorsPerFAT]
mov bx, 0x0002
mul bx
add ax, 1 ;AX is now the starting sector of the root directory in LBA
call LBAToCHS ;we now need to convert this into the CHS format
call ReadDisk ;Read the disk with the values calculated by the function.
mov cx, 0x0008
ReadFAT:
mov di, [0x7E00]
mov si, [KERNEL]
cmp si, di
jne _NotFound
inc si
inc di
dec cx
cmp cx, 0x0000
je _LoadEntry
jne ReadFAT
_LoadEntry:
mov si, KERF
call BPrint
cli
hlt
_NotFound:
mov si, KERNF
call BPrint
cli
hlt
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
BPrint:
mov ah, 0x0E
_BPrintLoop:
lodsb
cmp al, 0
je _BDone
int 0x10
jmp _BPrintLoop
_BDone:
ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ResetDisk:
pusha
mov ah, 0x00
mov dl, 0x00
int 0x13
jc DiskError
popa
ret
ReadDisk:
pusha
mov si, READING
call BPrint
popa
mov ah, 0x02
mov bx, 0x7E00 ;ES:BX 0x0000:0x7E00
int 0x13
jc DiskError
ret
DiskError:
pusha
mov si, DISKERR
call BPrint
popa
mov al, 0x00
mov al, ah
call WriteHex
cli
hlt
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
LBAToCHS:
mov dx, 0x0000 ;AX = LBA
div word [bpbSectorsPerTrack] ;AX = LBA/SPT, DX = AbsoluteSector - 1
push dx ;Store sector on stack
div word [bpbHeadsPerCylinder] ;AX = Cylinder, DX = head
pop bx ;store the sector into BX from stack
inc bx ;BX = Sector
mov ch, bl ;Lower 8 bits [First 8 bits of the cylinder] into the upper 8 bits of CH
mov cl, bh ;Upper 8 bits [Last 2 bits of the cylinder located here]
shl cl, 6 ;move the bits over by six so 00000011 would look like 11000000
or cl, al ;CX should now be a proper 10 bit cylinder and 6 bit sector with dl as the head
mov dh, 0x00 ;Zero out the DH register
xchg dh, dl ;Move the head value into the DH register and zero out the DL register
ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
WriteHex:
mov ah, 0x0E
LEA bx, [HEX]
mov ch, al
shr al, 4 ;AL now equals the Upper nibble
and al, 0x0F ;Mask is so only the lower nibble is printed
xlat ;Compare AL to our table at 0x0000:0x7E00(DS:BX)
int 0x10
shl ch, 4
shr ch, 4
mov al, ch
and al, 0x0F
xlat
int 0x10
ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
READING db 'Reading Disk...', 0x0A, 0x0D, 0
DISKERR db '!!ATTENTION!! - Disk Error. INT - 0x13 : AH - 0x', 0
KERNF db '!!ATTENTION!! - No Kernel found. Halting', 0x0A, 0x0D, 0
KERNEL db 'TerSysVI BIN'
KERF db 'Kernel found. Loading Kernel from disk...', 0x0A, 0x0D, 0
HEX db '0123456789ABCDEF'
times 510 - ($-$$) db 0
dw 0xAA55
Code: Select all
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Function: LBAToCHS
; Description: Translate Logical block address to CHS (Cylinder, Head, Sector).
; Works for all valid FAT12 compatible disk geometries.
;
; Resources: http://www.ctyme.com/intr/rb-0607.htm
; https://en.wikipedia.org/wiki/Logical_block_addressing#CHS_conversion
; https://stackoverflow.com/q/45434899/3857942
; Sector = (LBA mod SPT) + 1
; Head = (LBA / SPT) mod HEADS
; Cylinder = (LBA / SPT) / HEADS
;
; Inputs: AX = LBA
; Outputs: DL = Boot Drive Number
; DH = Head
; CH = Cylinder (lower 8 bits of 10-bit cylinder)
; CL = Sector/Cylinder
; Upper 2 bits of 10-bit Cylinders in upper 2 bits of CL
; Sector in lower 6 bits of CL
; AX = Clobbered
;
; Notes: Output registers match expectation of Int 13h/AH=2 inputs
;
LBAToCHS:
xor dx, dx ; Upper 16-bit of 32-bit value set to 0 for DIV
div word [bpbSectorsPerTrack] ; 32-bit by 16-bit DIV : LBA / SPT
mov cl, dl ; CL = S = LBA mod SPT
inc cl ; CL = S = (LBA mod SPT) + 1
xor dx, dx ; Upper 16-bit of 32-bit value set to 0 for DIV
div word [bpbHeadsPerCylinder]
; 32-bit by 16-bit DIV : (LBA / SPT) / HEADS
mov dh, dl ; DH = H = (LBA / SPT) mod HEADS
mov dl, [boot_drive] ; boot drive
mov ch, al ; CH = C(lower 8 bits) = (LBA / SPT) / HEADS
shl ah, 6 ; Store upper 2 bits of 10-bit Cylinder into
or cl, ah ; upper 2 bits of Sector (CL)
ret
Code: Select all
mov ax, word [bpbSectorsPerFAT]
mov bx, 0x0002
mul bx
Code: Select all
mov ax, word [bpbSectorsPerFAT]
xor bh, bh
mov bl, [bpbNumberOfFATs]
mul bx