Page 1 of 1
Bootloader won't load kernel
Posted: Thu Jun 13, 2013 11:46 pm
by tomplast
Hi fellow programmers
.
I work with c# professionally but I want to code in a "real language" on my spare time so I decided to take up the good ol' Assembly coding once again
. I have "stealed" some code from different places to try and create a bootloader with loads a kernel from the second sector of the floppy drive. The only problem is that the kernel never get's loaded I think, I would be very grateful if any of you could take a look at it
.
I know I'm very rusty when it comes to Assembly and especially os development, so please bare with me
. I'm here to learn and improve, all help is much appreciated
.
bootloader.asm
Code: Select all
org 0x7c00
jmp start
;Data
heading_message db ‘** bluberry Boot Loader **’, 0x0d, 0x0a, 0
loading_message db ‘ Loading kernel…’, 0x0d, 0x0a, 0
PrintString:
lodsb
or al, al
jz PrintString_Complete
mov ah, 0x0e
int 0×10
jmp PrintString
PrintString_Complete:
ret
LoadKernel:
mov ah, 0×2 ;BIOS read sector function
mov al, 0×1 ;Number of sectors to read
mov ch, 0×0 ;Track
mov cl, 0×2 ;Sector
mov dh, 0×0 ;Head
mov dl, 0×0 ;Drive
mov bx, 0×2000
mov es, bx
mov bx, 0×0000
int 0×13
mov ax, 0×2000
mov ds, ax
push word 0×2000
push word 0
retf
;jmp 0×2000:0×0000
start:
mov si, heading_message
call PrintString
mov si, loading_message
call PrintString
call LoadKernel
times 510 – ($ – $$) db 0
dw 0xAa55
kernel.asm
Code: Select all
jmp start
kernel_loaded db ‘Welcome to blueberry’, 0
PrintString:
lodsb
or al, al
jz PrintString_Complete
mov ah, 0x0e
int 0×10
jmp PrintString
PrintString_Complete:
ret
start:
mov si, kernel_loaded
call PrintString
jmp $
P.S I'm using QEMU for trying out my code and using the following to "bake" my bootloader and kernel together:
dd if=bootloader.bin of=fda.bin bs=512 count=1
dd if=kernel.bin of=fda.bin bs=512 count=1 seek=512
D.S
Re: Bootloader won't load kernel
Posted: Fri Jun 14, 2013 12:49 am
by iansjack
This is not really the place to teach assembly basics. I think you need to start with some simpler examples and single-step through them, using a debugger, until you are happy that you understand what is happening. For starters, just try loading a single sector into a particular location and check that that works as expected.
Re: Bootloader won't load kernel
Posted: Fri Jun 14, 2013 12:52 am
by tomplast
iansjack wrote:This is not really the place to teach assembly basics. I think you need to start with some simpler examples and single-step through them, using a debugger, until you are happy that you understand what is happening. For starters, just try loading a single sector into a particular location and check that that works as expected.
I appreciate the advice but I prefer to learning by trying and the bootloader works. It's just the loading of the second sector that won't work, I would appreciate any insights you have into the problem.
Re: Bootloader won't load kernel
Posted: Fri Jun 14, 2013 12:56 am
by iansjack
There is no better way of learning, and understanding, assembler code than single-stepping through it in a debugger. You are going to come up against far more esoteric problems than this; get into good habits and learn your debugging techniques now.
Re: Bootloader won't load kernel
Posted: Fri Jun 14, 2013 1:17 pm
by DavidCooper
The numbers in registers to set up the loading of the 2nd sector are all correct, so you can't be far away from getting it working. It's just possible that you're loading your kernel on top of the stack. You should also do something about that ugly push-push far ret which ought to be a far call [edit: I actually meant far jump]. Something you could try is printing part of the message in the kernel using code in the boot sector before jumping to the kernel - that would show up if it has actually loaded. You could, for example, write an extra print routine to print a few bytes out of the middle of the message.
I don't work with assembler so I don't know how your code gets tied together, but if you use a hex editor to extract the first two sectors from your disk and post the hex here, I can read what the resulting machine code does and tell you where it's failing. You shouldn't really need that kind of help though as there are plenty of debugging techniques you can apply first to find out where the problem lies. You can look to see if the 2nd sector is loading, you can check to see if something else is loading in the place it's supposed to load, you can collect the bytes that have loaded in and see if SI is going to be loaded with the right address for the string to be printed (though you can do that more easily by looking directly at your machine code with a hex editor), etc.
Edit: And don't assume the drive number is 0 - use the value passed to you in DL by the BIOS instead.
Re: Bootloader won't load kernel
Posted: Sat Jun 15, 2013 5:05 am
by Prochamber
You didn't setup a stack or set the data segment. You should not trust BIOS to have done either of those correctly.
You need to setup a stack first.
Code: Select all
cli ; Always clear interrupts before changing the stack
mov ax, 0x0000 ; Set a stack location before the bootloader code
mov ss, ax
mov sp, 0x7C00
sti ; Remember to restore interrupt
This code will setup a stack just before the bootloader, the stack works backwards (lower addresses), so it will use addresses below 0x0000:7C00.
You will need to setup the Data Segment (DS register) before you can do any memory access, i.e reading characters from a string.
Since you have ORG'd to 0x7C00 you will need to set it to a zero offset.
Re: Bootloader won't load kernel
Posted: Sat Jun 15, 2013 5:15 am
by Griwes
s/mov sp, 0x07C0/mov sp, 0x7C00/
Learn to do your addressing properly before answering a question.
Re: Bootloader won't load kernel
Posted: Sat Jun 15, 2013 7:27 pm
by Prochamber
Griwes wrote:s/mov sp, 0x07C0/mov sp, 0x7C00/
Learn to do your addressing properly before answering a question.
There is nothing wrong with my addressing. I've done a lot in real mode and I know how the addressing works.
I use a similar stack in the bootloader for my own operating system.
Your code would put the stack at the address 0x07C0:7C00 = 0xF800, which would still work but would use a different area.
The aim of my code was to use otherwise unoccupied space (below the bootloader).
Source:
OSDev - x86 Memory Map
Yes, I used the address of the bootloader but it won't actually put any data to the bootloader because the address will be decreased before storing any data.
Source:
The Art of Assembly (16 bit edition) - Chapter 6 - The PUSH and POP Instructions.
Re: Bootloader won't load kernel
Posted: Sat Jun 15, 2013 10:27 pm
by Mikemk
Is it just me or do half the OP's x's look like the multiplication sign character?
How are you compiling this?
Re: Bootloader won't load kernel
Posted: Sat Jun 15, 2013 10:40 pm
by AndrewBuckley
Prochamber please reread the change offered by Griwes. his change does not affect your stask segment, only where you put the pointer. you're off by 4 bits magnitude.
Re: Bootloader won't load kernel
Posted: Sat Jun 15, 2013 11:56 pm
by Prochamber
Merlin wrote:Prochamber please reread the change offered by Griwes. his change does not affect your stask segment, only where you put the pointer. you're off by 4 bits magnitude.
Oh, now I get it.
I accidental wrote 0x07C0 instead of 0x7C00 in the code. I've correct my post.
Re: Bootloader won't load kernel
Posted: Mon Jun 24, 2013 1:05 pm
by computertrick
You should install gcc on linux and access qemu's debug console and read from the memory address 0x2000 using the xp command to see if their has been any data loaded in their you could also use x/20 0x2000 which would print 20 bytes and if you wanted to disassemble use x/20i 0x2000
Re: Bootloader won't load kernel
Posted: Mon Jun 24, 2013 4:40 pm
by Rew
For early on development and getting acquainted with both assembly syntax and the intricacies of the x86 command set, I found bochs with built in debugger to be a convenient and invaluable tool. Also, you will need to find your preferred tool for disassembling and finding addresses of interest. Treat debugging assembly as if you were in visual studio, you want to see what is happening, so put a breakpoint at the beginning of your start function. Step each instruction. Check ESP and map to your disassembler addresses. Check all your "local variables" (registers) and "static variables" (memory locations) after each step and you will quickly find where your path diverges from expected.
Most importantly, when something does not work as expected, I find it easiest to check "http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html" and read the documentation on the instruction in question. When diagnosing a problem and you can't figure out what is wrong, review "Volume 1". The review it again, then again so you find what you missed the first 10 times through. In this case, section 3.3 and 3.4.2 might have helpful information to review. After that, reread the instruction and you will probably see what you missed setting up beforehand to make it work.
As mentioned by others, the things I would focus on for right now when debugging are segment registers and stack location. The reason for focusing on these can be found in the first paragraph or two of the documentation of the call instruction and jump instruction.
P.S. As harsh as it seems, as can be observed by the first couple responses, this community is critical of basic code specific questions for the most part. There is an abundance of knowledge and helpful individuals with regards to O.S. and architecture design and theory. But, if you're going to succeed in an O.S. project, you will need to setup an environment where you can be self sufficient on debugging code, and rely on the community for technical knowledge. Some people are a bit abrasive about this point, but truly for this type of project there is no better help then encouraging someone to learn how an architecture works by debugging or finding enough to ask the community about a specific technical question they don't understand.