I've been working on an operating system for a week or two, very lightly as a hobby, but can't get it to boot on a real computer. Specifically, the first stage of the bootloader starts correctly, and loads the second stage and kernel, but it is unable to start the second stage.
Here is the first stage of my bootloader: https://git.scd31.com/laptopdude90/Stev ... otsect.asm
The screen fills up with "sector loaded" messages, and then afterward fills up with "Starting bootloader second stage..." followed by "Loading SteveOS..." one after another in an infinite loop. I'm guessing there's some kind of problem when the program tries to "jmp" to the memory address holding the second stage. I'm not sure why it isn't working, and especially why it only has problems on a real machine.
My OS boots in qemu, but will not work on a real computer
Re: My OS boots in qemu, but will not work on a real compute
This is probably the single most "why not" question here, with the answer being almost the same every time.
You don't set you DS segment register at all. QEMU probably sets it to 0x0000, which makes your code work, while your real hardware probably sets it to 0x0040 or something else.
Set the DS (and ES, SS, etc) registers before you access memory.
i.e.: Before
Ben
- http://www.fysnet.net/osdesign_book_series.htm
You don't set you DS segment register at all. QEMU probably sets it to 0x0000, which makes your code work, while your real hardware probably sets it to 0x0040 or something else.
Set the DS (and ES, SS, etc) registers before you access memory.
i.e.: Before
Code: Select all
mov [BOOT_DRIVE], dl
- http://www.fysnet.net/osdesign_book_series.htm
Re: My OS boots in qemu, but will not work on a real compute
Another common mistake is to assume that uninitialised variables are 0, which can cause all manner of strange errors. (Although I agree that in this case assumptions about the segment registers are more likely.)
Re: My OS boots in qemu, but will not work on a real compute
Thank you very much. I managed to break my OS, so I can't test your solution, but I'll let you know as soon as I do.BenLunt wrote:This is probably the single most "why not" question here, with the answer being almost the same every time.
You don't set you DS segment register at all. QEMU probably sets it to 0x0000, which makes your code work, while your real hardware probably sets it to 0x0040 or something else.
Set the DS (and ES, SS, etc) registers before you access memory.
i.e.: Before
BenCode: Select all
mov [BOOT_DRIVE], dl
- http://www.fysnet.net/osdesign_book_series.htm
Re: My OS boots in qemu, but will not work on a real compute
Okay, so I tried setting the registers mentioned to 0. However, the system hangs at "Starting bootloader second stage...", which is different from before, but the system still refuses to boot.
Re: My OS boots in qemu, but will not work on a real compute
I quickly looked over your code a bit. You have a lot of redundant code as well as other minor errors.
For example, you pusha/popa before you call the disk code, which also pusha/popa as well.
Anyway, I think you need to eliminate the use of CHS and use LBA addressing. This way, you only have to increment a single 16-bit (32-bit) value for each sector. Then, and only then, at the time you call the INT 13h service, if needed, you convert LBA to CHS. Besides, if you are on a hard drive, you can eliminate the CHS altogether.
Get the idea? I think this will help you eliminate errors and problems.
For another point, a boot sector gets written to the media once, and never changes until a clean format. Either way, it will always be for that format; floppy, hard drive, etc., and will always know that it is a floppy, hard drive, etc. Therefore, write your boot sector for that specific media type only. Then write another for the other media types.
Now, before someone gets all out of shape, you can write all of the media independent code in one file, then use %if/#if/.if directives to assembly the boot sector for a specific media.
For example:
This is what all of my boot sectors do. I have a single (some times two) file(s) for each file system format, but a single file for each media format. If I change how the floppy is read, all I have to do is re-assemble all other files...i.e.: re-build the project.
For an older version of my boot code, go to https://github.com/fysnet/FYSOS/tree/master/boot for an example.
Ben
- http://www.fysnet.net/osdesign_book_series.htm
For example, you pusha/popa before you call the disk code, which also pusha/popa as well.
Anyway, I think you need to eliminate the use of CHS and use LBA addressing. This way, you only have to increment a single 16-bit (32-bit) value for each sector. Then, and only then, at the time you call the INT 13h service, if needed, you convert LBA to CHS. Besides, if you are on a hard drive, you can eliminate the CHS altogether.
Code: Select all
mov cur_lba, 2 ; starting LBA of (2nd stage) boot code
...
...
call load_boot_code
...
...
load_boot_code:
mov ax,cur_lba
cmp dl,80h
jae load_use_ext_services
call convert_ax_to_chs
mov es, ... address_to_load ...
jmp do_call_the_call
load_use_ext_services:
mov ah,42h
mov si, ... packet ...
do_call_the_call:
int 13h
For another point, a boot sector gets written to the media once, and never changes until a clean format. Either way, it will always be for that format; floppy, hard drive, etc., and will always know that it is a floppy, hard drive, etc. Therefore, write your boot sector for that specific media type only. Then write another for the other media types.
Now, before someone gets all out of shape, you can write all of the media independent code in one file, then use %if/#if/.if directives to assembly the boot sector for a specific media.
For example:
Code: Select all
... media independent code here ....
...
mov ax,starting_lba
call load_sectors
...
...
#ifdef FOR_FLOPPY
load_sectors:
; write code for floppy media here
ret
#endif
#ifdef FOR_HARD_DRIVE
load_sectors:
; write code for floppy media here
ret
#endif
For an older version of my boot code, go to https://github.com/fysnet/FYSOS/tree/master/boot for an example.
Ben
- http://www.fysnet.net/osdesign_book_series.htm
- MSDOSDudeNot
- Posts: 15
- Joined: Wed Jun 06, 2018 9:15 pm
Re: My OS boots in qemu, but will not work on a real compute
I looked at your boot loading code, and if it's crashing, hanging, or getting stuck at or after the 'Starting bootloader second stage...' message, then it's either when you are calling the 'load_bootloader' routine, or when you are far jumping to the boot loaders' second stage main entry point.
If it is this:
Then you need to check your disk code. There could be either possibly be an loop somewhere, or there could be some code that is getting the computer struck. I can't see the 'disk.asm' file, so only you can know what's inside of it.
If it is this:
Then your jump to the second stage of your boot loader is broken. One possibly is it's actually, somehow, hitting the instruction; that's probably unlikely, though.
It could also be that your is faulty, and is actually set to a inaccurate value. I've had that happen to me also, when I was trying to write a Protected Mode boot loader program. I completely failed at far jumping, and far jumped to the wrong place, then I got nothing but a black screen.
All in all, if it's getting stuck at that specific point, then it can only be something that was past that point, and most likely very close to that point. Hope this helps.
If it is this:
Code: Select all
mov bx, STARTED_LOADING
call print
call print_nl
call load_bootloader
If it is this:
Code: Select all
mov bx, STARTING_STAGE
call print
call print_nl
jmp BOOTLOADER_OFFSET
jmp $
Code: Select all
jmp $
It could also be that your
Code: Select all
BOOTLOADER_OFFSET
All in all, if it's getting stuck at that specific point, then it can only be something that was past that point, and most likely very close to that point. Hope this helps.