Second Stage Loader
Second Stage Loader
Hello, I'm making a kernel in NASM. I have a bootsector program, but how do I load another program off the disk? I don't want to use a file system. So I used:
; Boot.asm
ORG 0
jmp 07C0h:start
start:
; Update the segment registers
mov ax, cs
mov ds, ax
mov es, ax
reset: ; Reset the floppy drive
mov ax, 0 ;
mov dl, 0 ; Drive=0 (=A)
int 16h ;
jc reset ; ERROR => reset again
read:
mov ax, 1000h ; ES:BX = 1000:0000
mov es, ax ;
mov bx, 0 ;
mov ah, 2 ; Load disk data to ES:BX
mov al, 5 ; Load 5 sectors
mov ch, 0 ; Cylinder=0
mov cl, 2 ; Sector=2
mov dh, 0 ; Head=0
mov dl, 0 ; Drive=0
int 13h ; Read!
jc read ; ERROR => Try again
jmp 1000h:0000 ; Jump to the program
times 510-($-$$) db 0
dw 0AA55h
; End of boot.asm
; 2ndboot.asm
mov ax, 13h
int 10h
; end of 2ndboot.asm
; kernel.asm
%include 'boot.asm'
%include '2ndboot.asm'
; end of kernel.asm
And I compiled the kernel & put it on a floppy like this;
nasm -f bin kernel.asm -o kernel.bin
dd if=kernel.bin of=/dev/fd0
Now, when the floppy boots, all the code before 2ndboot.asm works, or at least before calling reset.
What am i doing wrong?
Thank you
; Boot.asm
ORG 0
jmp 07C0h:start
start:
; Update the segment registers
mov ax, cs
mov ds, ax
mov es, ax
reset: ; Reset the floppy drive
mov ax, 0 ;
mov dl, 0 ; Drive=0 (=A)
int 16h ;
jc reset ; ERROR => reset again
read:
mov ax, 1000h ; ES:BX = 1000:0000
mov es, ax ;
mov bx, 0 ;
mov ah, 2 ; Load disk data to ES:BX
mov al, 5 ; Load 5 sectors
mov ch, 0 ; Cylinder=0
mov cl, 2 ; Sector=2
mov dh, 0 ; Head=0
mov dl, 0 ; Drive=0
int 13h ; Read!
jc read ; ERROR => Try again
jmp 1000h:0000 ; Jump to the program
times 510-($-$$) db 0
dw 0AA55h
; End of boot.asm
; 2ndboot.asm
mov ax, 13h
int 10h
; end of 2ndboot.asm
; kernel.asm
%include 'boot.asm'
%include '2ndboot.asm'
; end of kernel.asm
And I compiled the kernel & put it on a floppy like this;
nasm -f bin kernel.asm -o kernel.bin
dd if=kernel.bin of=/dev/fd0
Now, when the floppy boots, all the code before 2ndboot.asm works, or at least before calling reset.
What am i doing wrong?
Thank you
Re:Second Stage Loader
First of all, when you do this:
reset: ; Reset the floppy drive
mov ax, 0 ;
mov dl, 0 ; Drive=0 (=A)
int 16h ;
jc reset ; ERROR => reset again
you don't reset the floppy but get a keystroke! You must use int 13h to reset the controller.
Then I don't know why you include your boot in the kernel... remember that boot loader is a thing, and kernel is another!
In the first sector of the floppy you must put only the boot.asm and in the next sectors you can put your kernel.. that is loaded by the boot.asm!
reset: ; Reset the floppy drive
mov ax, 0 ;
mov dl, 0 ; Drive=0 (=A)
int 16h ;
jc reset ; ERROR => reset again
you don't reset the floppy but get a keystroke! You must use int 13h to reset the controller.
Then I don't know why you include your boot in the kernel... remember that boot loader is a thing, and kernel is another!
In the first sector of the floppy you must put only the boot.asm and in the next sectors you can put your kernel.. that is loaded by the boot.asm!
Re:Second Stage Loader
Ok, but how do I put the kernel on other parts of the disk? Using dd in linux? Thank you
Re:Second Stage Loader
I have three suggestions for you that will make your code easier and might solve your problem:
1. The reset drive should be like this:
reset: ; reset the fl;oppy drive
mov ax,0
mov dl,0 ; drive = 0 (floppy drive a)
int 13h ; was recently int 16h
jc reset ; if error, reset again
2. you should change the 2ndboot.asm program to this:
This has to be there in order for both programs to work!
[org 1000:0000] or simply [org 0]
mov ax,13h = mov ax,13 (its the same thing!)
3. times 510-($-$$) db 0
dw 0xAA55h
The dw 0xAA55h should be dw 0xAA55
The computer won't recongize the h on the end which represents the letter symbol for hexadecimal. It only works on the interrupt commands. (ex: int 13h or int 0x13, same thing)
Hope this helps!
1. The reset drive should be like this:
reset: ; reset the fl;oppy drive
mov ax,0
mov dl,0 ; drive = 0 (floppy drive a)
int 13h ; was recently int 16h
jc reset ; if error, reset again
2. you should change the 2ndboot.asm program to this:
This has to be there in order for both programs to work!
[org 1000:0000] or simply [org 0]
mov ax,13h = mov ax,13 (its the same thing!)
3. times 510-($-$$) db 0
dw 0xAA55h
The dw 0xAA55h should be dw 0xAA55
The computer won't recongize the h on the end which represents the letter symbol for hexadecimal. It only works on the interrupt commands. (ex: int 13h or int 0x13, same thing)
Hope this helps!
Re:Second Stage Loader
I also saw something else wrong with your code:
read:
mov ax, 1000h ; this is wrong
mov es, ax
mov bx, 0 ; this has to match
mov ah, 2
mov al, 5
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 0
int 13h
this is how it should be:
read:
mov ax,1000h ; this can be also mov bx,1000h
mov es,ax
mov ax,0 ; this can be also mov bx,0
mov ah,2
mov al,5
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 13h
Hope this helps!
read:
mov ax, 1000h ; this is wrong
mov es, ax
mov bx, 0 ; this has to match
mov ah, 2
mov al, 5
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 0
int 13h
this is how it should be:
read:
mov ax,1000h ; this can be also mov bx,1000h
mov es,ax
mov ax,0 ; this can be also mov bx,0
mov ah,2
mov al,5
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 13h
Hope this helps!
Re:Second Stage Loader
My boot sector is working now, all I had to do is change int 16h to 13h. Even though it's 0AA55h, and other things, my boot sector works. Now I have one more problem. I need to know how to link my boot sector with ld
Here is how I compile it for linking:
nasm -f aout boot.asm -o boot.o
Now how do I link it? I need to link it so I can have my C Kernel load - So I don't have to call it from the disk. I know how to call my kernel ( call main ; no '_' ). I don't know how to compile my C Kernel & link it to my boot sector.
After this, That's all the help I'll need in this thread, I think :-\
Thank you for all you help
& I like crazybudda's 'some code and stuff'
Here is how I compile it for linking:
nasm -f aout boot.asm -o boot.o
Now how do I link it? I need to link it so I can have my C Kernel load - So I don't have to call it from the disk. I know how to call my kernel ( call main ; no '_' ). I don't know how to compile my C Kernel & link it to my boot sector.
After this, That's all the help I'll need in this thread, I think :-\
Thank you for all you help
& I like crazybudda's 'some code and stuff'
Re:Second Stage Loader
This can be a bit trickier than you might think.
LD really expects to produce some kind of executable file format, such as elf or aout, and spit out some header etc. If you don't write some kind of loader for these formats, you'll be pretty stuck.
I'll give you some clues for how to get around this. In your boot code you read sectors containing a binary image to some memory locations to execute. To produce the binary image, you use LD to create an executable, then use OBJCOPY to strip it into a binary file. I would jump from the boot code to some stub assembly file for calling main.
here's an example
nasm stub.asm -f aout
gcc -c prog.cpp
ld -o prog.exe stub.o prog.o
objcopy -R .dynamic -R .net -R .comment -S -O binary \
prog.exe prog.bin
You can use DD to write it to disk (skipping the boot sector).
LD really expects to produce some kind of executable file format, such as elf or aout, and spit out some header etc. If you don't write some kind of loader for these formats, you'll be pretty stuck.
I'll give you some clues for how to get around this. In your boot code you read sectors containing a binary image to some memory locations to execute. To produce the binary image, you use LD to create an executable, then use OBJCOPY to strip it into a binary file. I would jump from the boot code to some stub assembly file for calling main.
here's an example
nasm stub.asm -f aout
gcc -c prog.cpp
ld -o prog.exe stub.o prog.o
objcopy -R .dynamic -R .net -R .comment -S -O binary \
prog.exe prog.bin
You can use DD to write it to disk (skipping the boot sector).
Re:Second Stage Loader
Eh? These two are not equal... 13h is 19 in decimal...beyondsociety wrote: mov ax,13h = mov ax,13 (its the same thing!)
Re:Second Stage Loader
No matter how I try to see what you mean, I can't...beyondsociety wrote: I also saw something else wrong with your code:
read:
mov ax, 1000h ; this is wrong
mov es, ax
mov bx, 0 ; this has to match
mov ah, 2
mov al, 5
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 0
int 13h
this is how it should be:
read:
mov ax,1000h ; this can be also mov bx,1000h
mov es,ax
mov ax,0 ; this can be also mov bx,0
mov ah,2
mov al,5
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 13h
Hope this helps!
mov ax, 1000h ; this is wrong
mov ax,1000h ; this can be also mov bx,1000h
When comparing the above, I see nothing that differs them apart.
mov bx, 0 ; this has to match
mov ax,0 ; this can be also mov bx,0
You write that "mov bx,0" should be changed to "mov ax,0" but in the comment you write that "mov bx,0" works too...??? Also, The pointer to the disk buffer must be in Es:Bx and cannot be placed in Ax.
Re:Second Stage Loader
Sorry about that, I am still learning assembly. The 13h = 19 in decimal is in fact correct. Thanks for correcting me peter_vigren!
Re:Second Stage Loader
You're welcome. We can all make mistakes...beyondsociety wrote: Sorry about that, I am still learning assembly. The 13h = 19 in decimal is in fact correct. Thanks for correcting me peter_vigren!