I am making an operating system called TriangleOS with a few files like sysldr.sys
, kernel.sys
, etc. When I run it on VMWare I get this error:
Remove disks or other media. Press any key to restart
I'm compiling on Windows 10. I am using partcopy
to create my boot sector. I typed:
partcopy.exe boot.asm 0 200 -f0
This is the content of my file boot.asm
:
bits 16
org 0
%include"Floppy16.inc"
start: jmp main
Print:
lodsb
or al, al
jz PrintDone
mov ah, 0eh
int 10h
jmp Print
PrintDone:
ret
main:
cli
mov ax, 0x07C0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x0000
mov ss, ax
mov sp, 0xFFFF
sti
mov si, msgLoading
call Print
LOAD_ROOT:
xor cx, cx
xor dx, dx
mov ax, 0x0020
mul WORD [bpbRootEntries]
div WORD [bpbBytesPerSector]
xchg ax, cx
mov al, BYTE [bpbNumberOfFATs]
mul WORD [bpbSectorsPerFAT]
add ax, WORD [bpbReservedSectors]
mov WORD [datasector], ax
add WORD [datasector], cx
mov bx, 0x0200
call ReadSectors
mov cx, WORD [bpbRootEntries]
mov di, 0x0200
.LOOP:
push cx
mov cx, 0x000B
mov si, ImageName
push di
rep cmpsb
pop di
je LOAD_FAT
pop cx
add di, 0x0020
loop .LOOP
jmp FAILURE
LOAD_FAT:
mov dx, WORD [di + 0x001A]
mov WORD [cluster], dx
xor ax, ax
mov al, BYTE [bpbNumberOfFATs]
mul WORD [bpbSectorsPerFAT]
mov cx, ax
mov ax, WORD [bpbReservedSectors]
mov bx, 0x0200
call ReadSectors
mov ax, 0x0050
mov es, ax
mov bx, 0x0000
push bx
LOAD_IMAGE:
mov ax, WORD [cluster]
pop bx
call ClusterLBA
xor cx, cx
mov cl, BYTE [bpbSectorsPerCluster]
call ReadSectors
push bx
mov ax, WORD [cluster]
mov cx, ax
mov dx, ax
shr dx, 0x0001
add cx, dx
mov bx, 0x0200
add bx, cx
mov dx, WORD [bx]
test ax, 0x0001
jnz .ODD_CLUSTER
.EVEN_CLUSTER:
and dx, 0000111111111111b
jmp .DONE
.ODD_CLUSTER:
shr dx, 0x0004
.DONE:
mov WORD [cluster], dx
cmp dx, 0x0FF0
jb LOAD_IMAGE
DONE:
mov si, msgCRLF
call Print
push WORD 0x0050
push WORD 0x0000
retf
FAILURE:
mov si, msgFailure
call Print
mov ah, 0x00
int 0x16
int 0x19
bootdevice db 0
ImageName: db "KRNLDR SYS"
msgLoading: db 0x0D, 0x0A, "Reading Kernel Loader", 0x00
msgCRLF: db 0x0D, 0x0A, 0x00
msgProgress: db ".", 0x00
msgFailure: db 0x0D, 0x0A, "Can't find Kernel Loader (krnldr.sys). Press Any Key to Reboot", 0x0D, 0x0A, 0x00
TIMES 510-($-$$) DB 0
DW 0xAA55
The file Floppy16.inc
is a file driver helper. Here is the code:
%ifndef __FLOPPY16_INC_
%define __FLOPPY16_INC_
bits 16
bpbOEM db "TriangOS"
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xf0
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "TOS FLOPPY "
bsFileSystem: DB "FAT12 "
datasector dw 0x0000
cluster dw 0x0000
absoluteSector db 0x00
absoluteHead db 0x00
absoluteTrack db 0x00
ClusterLBA:
sub ax, 0x0002
xor cx, cx
mov cl, BYTE [bpbSectorsPerCluster]
mul cx
add ax, WORD [datasector]
ret
LBACHS:
xor dx, dx
div WORD [bpbSectorsPerTrack]
inc dl
mov BYTE [absoluteSector], dl
xor dx, dx
div WORD [bpbHeadsPerCylinder]
mov BYTE [absoluteHead], dl
mov BYTE [absoluteTrack], al
ret
; CX=>Kolko sektori da procita
; AX=>Pocetni sektor
; ES:EBX=>Na koju mem. lokaciju da ga stavi
ReadSectors:
.MAIN
mov di, 0x0005
.SECTORLOOP
push ax
push bx
push cx
call LBACHS
mov ah, 0x02
mov al, 0x01
mov ch, BYTE [absoluteTrack]
mov cl, BYTE [absoluteSector]
mov dh, BYTE [absoluteHead]
mov dl, BYTE [bsDriveNumber]
int 0x13
jnc .SUCCESS
xor ax, ax
int 0x13
dec di
pop cx
pop bx
pop ax
jnz .SECTORLOOP
int 0x18
.SUCCESS
pop cx
pop bx
pop ax
add bx, WORD [bpbBytesPerSector]
inc ax
loop .MAIN
ret
%endif
I compiled the boot sector using this command:
nasm.exe -f bin boot.asm -o boot.bin
The project is really big. I made this so that I don't need GRUB. I noticed that my hex editor is at the end 55
. Is it normal to be reverse? In my code there is normal 0xAA55
. Why does it output Remove disks or other media?
How can I fix this problem? Any suggestions?
At the top of your code you do this:
bits 16
org 0
%include"Floppy16.inc"
start: jmp main
The %include"Floppy16.inc"
will insert everything in the file floppy16.inc
as if it were part of your boot.asm
code. The problem is that your Boot Parameter Block (BPB) appears before any code, so the data will literally be executed as code since the bootloader will start executing from physical address 0x07c00. I think you probably should have done this:
bits 16
org 0
start: jmp main
nop ; Place NOP so BPB starts at the 4th byte of binary file.
; relative(short) JMP is 2 bytes long. NOP acts as 1 byte padding.
%include"Floppy16.inc"
By jumping over the BPB data included by the file floppy16.inc
you avoid executing the data as code.
At boot, this output:
Remove disks or other media. Press any key to restart
Suggests there may have been a disk inserted in the system but that there was no bootable media found.
What I do find curious is that you seem to generate a binary file from your assembler code but then you use this command:
partcopy.exe boot.asm 0 200 -f0
This will place the assembler source code into the first 512 bytes of the floppy. You want to place the binary file you created onto the floppy. I think you should have used:
partcopy.exe boot.bin 0 200 -f0
File boot.bin
is the binary file that was created from this command:
nasm.exe -f bin boot.asm -o boot.bin
Since you copied boot.asm
into the boot sector of your floppy the last 2 bytes of the sector would NOT contain the word 0xAA55, and thus wouldn't be detected as a bootable floppy. If there was no other bootable media on your virtual machine you would have got the error about removing media and restarting.
Fifoernik mentioned in the comments:
Unrelated but still... Don't initialize your stackpointer at an odd address! Better use the even address mov sp, 0xFFFE
In the past couple days I wrote a Stackoverflow answer that discussed that issue as well. I'd probably suggest setting SP to 0x0000. A stack that is aligned to an odd word boundary (like 0xffff) will take a significant performance hit if run on real 8086 processors. Setting SP to zero works because it is an even address and the first push of a word onto the stack decrements SP by 2 first and then writes the value. The first word pushed would be at SS:0xfffe .
As it is your code won't run on anything less than a 386 anyway because you have:
mov fs, ax
mov gs, ax
fs
and gs
registers were introduced in the 386 processors. Your code wouldn't run on real 8086/8088/80188/80286 processors. This may be by design, but I felt I should mention it.
Since you are using instructions like lodsb
you should consider setting the direction flag. In your case you seem to be relying on forward movement so I'd recommend the us of the CLD
instruction near the beginning of the bootloader. You can't be guaranteed it will be set properly.
Your code seems to destroy the contents of DL. The BIOS will pass the boot drive to your bootloader through DL. You might consider saving it so that it can be used to read sectors from the drive that was booted. It is possible you are accounting for this, but it isn't readily apparent without seeing the contents of floppy16.inc