You need RAWWRITE to write it to a standard floppy. That image contains the source to a 512-byte bootstrap:
A copy to the dummy kernel source (NOT in floppy, and when compiled must be named KERNEL.BIN):
Code: Select all
org 7C00h
__MyKernelPlainEntry__ equ 0x100
_jmp: jmp short start
_nop: nop
_OEMid db " "
_bytesPerSect dw 0200h
_sectsPerClus db 001h
_resrvedSects dw 0001h
_numOfFATs db 002h
_numRootDirEntries dw 00E0h
_numSectors dw 0B40h
_mediaType db 0F0h
_numFATsectors dw 0009h
_sectorsPerTrack dw 0012h
_numHeads dw 0002h
_numHiddenSects dd 00000000h
_numSectorsHuge dd 00000000h
_driveNumber db 00h
_reserved db 00h
_signature db 29h
_volumeID db " "
_volumeLabel db " "
_FSType db "FAT12 "
;INIT: 448 free bytes:
;INIT: 448 free bytes:
;INIT: 448 free bytes:
;> cs = 0
;>> dl = drive we were booted from
;INIT: enable protected mode (time 1 out of 2) to load GDT
;INIT: enable protected mode (time 1 out of 2) to load GDT
;INIT: enable protected mode (time 1 out of 2) to load GDT
start: cli ;{0}
lgdt [cs:GDT] ;Load GDT.
mov ecx, CR0 ;Switch to protected mode
inc cx
mov CR0, ecx ;{5}
;END: enable protected mode (time 1 out of 2) to load GDT
;END: enable protected mode (time 1 out of 2) to load GDT
;END: enable protected mode (time 1 out of 2) to load GDT
;;INIT: enable A20
;;INIT: enable A20
;;INIT: enable A20
;registers modified in this INIT--END section:
;AX (EAX)
;registers wich values to reuse in the next INIT--END:
;AH (will be 0)
.5: in al, 0x64 ;Enable A20 {4A}.
test al, 2 ;see if bit 1 returned from port
;0x64 is 1, which means that
;controller is not ready
jnz .5 ;repeat until bit 1 from 0x64 is cleared to 0,
;indicating the keyboard controller is ready
mov al, 0xD1 ;*WRITE OUTPUT PORT* command
out 0x64, al ;send it
.6: in al, 0x64 ;read port 0x64
and ax, byte 2 ;see if bit 1 is set to 0
;NOTE: it will leave AH set to 0 at once
; to be used in the next INIT--END block.
jnz .6 ;repeat until keyboard controller is ready
;(bit 1 cleared to 0)
mov al, 0xDF ;configure keyb. controller bit-set
out 0x60, al ;send it to data port, to enable A20
;;END: enable A20
;;END: enable A20
;;END: enable A20
;;INIT: register/memory parameters configuration
;;INIT: register/memory parameters configuration
;;INIT: register/memory parameters configuration
;registers to modify in this INIT--END section:
;AX (EAX) 0
;DS 0
;ES 0x800
;SS 0
;SP 0x800
;registers with values to reuse in the next INIT--END block:
;apparently ALL of the above
;> ah = 0
;> dl = drive we were booted from
mov al,Data32
mov ds, ax ;{2} Extend limit for ds.
mov es, ax ;Extend limit for es.
dec cx ;Switch back to and into (Un)Real mode.
mov CR0, ecx ;{5}
;Here we are in (Un)Real Mode:
;Here we are in (Un)Real Mode:
;Here we are in (Un)Real Mode:
mov [_jmp], dl ;Save drive number we came from.
mov sp, 0x800 ;Configure stack end to 0x800
xor eax, eax ;Segment. 32 bits cleared to 0
mov ds, ax ;DS (Data Segment) cleared to 0
mov ss, ax ;SS (Stack Segment) cleared to 0
mov es, sp ;Read directory at 800:0 {1C}. ES
;(Extra Segment) 0x800.
;;END: register/memory parameters configuration
;;END: register/memory parameters configuration
;;END: register/memory parameters configuration
;;INIT: configure floppy information
;;INIT: configure floppy information
;;INIT: configure floppy information
;> eax = 00000000
;We keep in Unreal Mode from the previous INIT--END:
;We keep in Unreal Mode from the previous INIT--END:
;We keep in Unreal Mode from the previous INIT--END:
mov al, [_numOfFATs] ;Number of FATs
mul byte [_numFATsectors] ;Times size of FAT |(in sectors?)
add ax, [_resrvedSects] ;Plus Sectors before first FAT
;(_numOfFATs*_numFATsectors)+_resrvedSects
;eax = LBN of Root directory
movzx edi,word [_numRootDirEntries] ;Root directory entries
push di ; used again later
dec di ;Convert to number of sectors
shr di, 4 ;16 directory entries per sector
inc di
call read_sectors ;call forward
;;END: configure floppy information
;;END: configure floppy information
;;END: configure floppy information
;;INIT: look for 8.3 name in the floppy root directory
;;INIT: look for 8.3 name in the floppy root directory
;;INIT: look for 8.3 name in the floppy root directory
;> eax = LBN of root directory
;> edi = length of root directory in sectors
;> [sp] = length of root directory in entries
;> esi = 00000000
;We keep here in Unreal Mode from the 2 previous INIT--END blocks:
;We keep here in Unreal Mode from the 2 previous INIT--END blocks:
;We keep here in Unreal Mode from the 2 previous INIT--END blocks:
lea ebp, [eax+edi] ;ebp = LBN of cluster 2
pop bx ;Root directory entries.
xor di, di ;Point at directory {1C}
.20: mov si, kernelFile ;Name of file we want.
xor ecx, ecx
mov cl, 11 ;bytes in string "KERNEL BIN"
a32 rep cmpsb ;Found the file?.
;we use the 11 in CL
je found ;Yes
add cl, 21 ;Offset to next directory entry
add edi, ecx ;Advance to next entry
dec bx ;Loop through all entries
jnz .20
;Couldn't find file in directory
boot_error:
disk_error:
mov ax, 0xE07 ;{3}
int 10h ;Ring the bell on error...
jmp short $ ;end with infinite loop
;;END: look for 8.3 name in the floppy root directory
;;END: look for 8.3 name in the floppy root directory
;;END: look for 8.3 name in the floppy root directory
;;INIT: read file according what the previous INIT--END found
;;INIT: read file according what the previous INIT--END found
;;INIT: read file according what the previous INIT--END found
;>> ecx = 00000000
;> es = 800
;> es:edi = Directory entry of file
;> ebp = LBN of cluster 2
;> eax = 0000????
found: push word [es:edi+0xF] ;Starting cluster of file
mov di, [_numFATsectors] ;Size of FAT (in sectors)
mov ax, [_resrvedSects] ;LBN of FAT
call read_sectors ;call forward
mov bx, 0x4000
mov es, bx ;es = 0x4000
mov edi, __MyKernelPlainEntry__-0x40000 ;{1D}{4B} One megabyte minus ES base
;;END: read file according what the previous INIT--END found
;;END: read file according what the previous INIT--END found
;;END: read file according what the previous INIT--END found
;;INIT: final processes and control transfer to kernel entry point
;;INIT: final processes and control transfer to kernel entry point
;;INIT: final processes and control transfer to kernel entry point
.10:
;>> ecx = 0000????
;> [sp] = Next cluster of file
;> esi = 0000????
;>> edx = 0000????
;> es:edi = Destination address
;> ebp = LBN of cluster 2
;> ds = 0
xor eax, eax
pop si ;Next cluster of file
mov bx, si
cmp si, 0xFF8 ;Valid cluster?
jae eof ;No: assume end of file
;Yes: (c-bit set)
rcr bx, 1 ;bx = 0x8000 + cluster/2
mov bx, [bx+si] ;Get word containing FAT entry
jnc .11 ;Entry is low 12 bits
shr bx, 4 ;Entry was high 12 bits
.11: and bh, 0xF ;Mask to just 12 bits
push bx ;Save cluster after next
push di ;Save destination address {7}
mov al, [_sectsPerClus] ;Size of each cluster
mov di, ax ; (in sectors)
dec si
dec si
mul esi ;Times cluster number minus 2
add eax, ebp ;Plus LBN of cluster 2
call read_sectors ;Read that cluster
;> ecx = 0000????
;>> edx = 0000????
;> di = Clustersize in sectors
;> esi = 0
;>> ebp = LBN of cluster 2
;> [sp] = Bottom 16-bits of destination address {7}
;>> [sp+2] = Following cluster
;> ds = 0
;> es = 4000
mov cx, di ;Cluster size in sectors
xchg ch, cl ;Cluster size in words
pop di ;Restore destination address {7}
es a32 rep movsw
jmp short .10 ;Loop until end of file
;> eax = 0
;> edx = 0000????
;> bx = 0FF?
eof:
.20:
int 8 ;{8}
loop .20
cli ;{6}
mov eax, CR0 ;Turn on protected mode
or eax, 0x00000001
mov CR0, eax
mov cl, Data32 ;Setup ds and es
push cx ;{5}
pop ds
mov es, cx
a32 jmp dword Code32:__MyKernelPlainEntry__ ;Go
;;END: final processes and control transfer to kernel entry point
;;END: final processes and control transfer to kernel entry point
;;END: final processes and control transfer to kernel entry point
;;INIT: read_sectors
;;INIT: read_sectors
;;INIT: read_sectors
read_sectors:
; Input:
; EAX = LBN
; DI = sector count
; ES = segment
; Output:
; EBX high half cleared
; DL = drive #
; EDX high half cleared
; ESI = 0
; Clobbered:
; BX, CX, DH
push eax
push di
push es
.10: push eax ;LBN
cdq ;edx = 0
movzx ebx, byte [_sectorsPerTrack]
div ebx ;EAX=track ;EDX=sector-1
mov cx, dx ;CL=sector-1 ;CH=0
sub bl, dl ;BX = max transfer before end of track
cmp di, bx ;Do we want more than that?
ja .20 ;Yes, do just this much now
mov bx, di ;No, do it all now
.20: mov esi, ebx ;Save count for this transfer.
inc cx ;CL=Sector number
xor dx, dx
mov bl, [_numHeads]
div ebx ;EAX=cylinder ;EDX=head
mov dh, dl ;Head
mov dl, [_jmp] ;Drive number
xchg ch, al ;CH=Low 8 bits of cylinder number; AL=0
shr ax, 2 ;AL[6:7]=High two bits of cylinder
or cl, al ;CX = Cylinder and sector
mov ax, si ;Sector count
mov ah, 2 ;Read
xor bx, bx
push ax
int 13h
pop ax
jnc .30
int 13h ;If at second you don't succeed, give up
jc near disk_error
.30: pop eax
add eax, esi ;Advance LBN
push si
shl si, 5
mov bx, es
add bx, si ;Advance segment
mov es, bx
pop si
sub di, si
ja .10
pop es
pop di
pop eax
xor si, si
ret
;;END: read_sectors
;;END: read_sectors
;;END: read_sectors
kernelFile db 'KERNEL BIN'
;INIT: GDT
;INIT: GDT
;INIT: GDT
GDT:
_SELNulo equ 0 ;WARNING: this sector, besides being the GDT pointer,
GDT_size: ; is the NULL selector.
dw GDTsize
GDT_actualptr:
dd GDT
dw 0x0000
Code32 equ 8
dw 0FFFFh ; bits 0-15 length
dw 00000h ; bits 0-15 base addr
db 0 ; bits 16-23 base addr
db 10011010b ; bits P,DPL,DT & type
db 11001111b ; bits G,D & bits 16-19 length
db 0 ; bits 24-31 base addr
Data32 equ 16
dw 0FFFFh ; bits 0-15 length
dw 00000h ; bits 0-15 base addr
db 0 ; bits 16-23 base addr
db 10010010b ; bits P,DPL,DT & type
db 11001111b ; bits G,D & bits 16-19 length
db 0 ; bits 24-31 base addr
GDT_end:
GDTsize equ (GDT_end-GDT)-1
;END: GDT
;END: GDT
;END: GDT
times (510-($-$$)) db 0
;END: 448 free bytes
;END: 448 free bytes
;END: 448 free bytes
dw 0xAA55