Reputation: 21
I know that with a simple kernel this small I don't actually need to boot it with GRUB but I am trying to learn how to do this before my kernel gets big and I need to boot it. I have written a simple kernel with assembly using the real mode assembly tutorials over at OSDev.org. I tried to boot it but GRUB gave me the error that it couldn't find the multi-boot header. I took a look at the assembly code for the C Bare Bones tutorial. Do I just have to put everything in the section .multiboot? Can you please show me how I would boot this code. (This code is not of my creation, I have left my code on my home machine and am at school right now, I just borrowed this code from OSDev so please don't give me any mean comments saying that I stole someone's code. )
; boot.asm
mov ax, 0x07c0
mov ds, ax
mov si, msg
ch_loop:lodsb
or al, al ; zero=end or str
jz hang ; get out
mov ah, 0x0E
int 0x10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
Can I boot and print using the BIOS or do I have o use a stack?
;====================================
[ORG 0x7c00] ; add to offsets
xor ax, ax ; make it zero
mov ds, ax ; DS=0
mov ss, ax ; stack starts at 0
mov sp, 0x9c00 ; 200h past code start
mov ax, 0xb800 ; text video memory
mov es, ax
mov si, msg ; show text string
call sprint
mov ax, 0xb800 ; look at video mem
mov gs, ax
mov bx, 0x0000 ; 'W'=57 attrib=0F
mov ax, [gs:bx]
mov word [reg16], ax ;look at register
call printreg16
hang:
jmp hang
----------------------
dochar: call cprint ; print one character
sprint: lodsb ; string char to AL
cmp al, 0
jne dochar ; else, we're done
add byte [ypos], 1 ;down one row
mov byte [xpos], 0 ;back to left
ret
cprint: mov ah, 0x0F ; attrib = white on black
mov cx, ax ; save char/attribute
movzx ax, byte [ypos]
mov dx, 160 ; 2 bytes (char/attrib)
mul dx ; for 80 columns
movzx bx, byte [xpos]
shl bx, 1 ; times 2 to skip attrib
mov di, 0 ; start of video memory
add di, ax ; add y offset
add di, bx ; add x offset
mov ax, cx ; restore char/attribute
stosw ; write char/attribute
add byte [xpos], 1 ; advance to right
ret
;------------------------------------
printreg16:
mov di, outstr16
mov ax, [reg16]
mov si, hexstr
mov cx, 4 ;four places
hexloop:
rol ax, 4 ;leftmost will
mov bx, ax ; become
and bx, 0x0f ; rightmost
mov bl, [si + bx];index into hexstr
mov [di], bl
inc di
dec cx
jnz hexloop
mov si, outstr16
call sprint
ret
;------------------------------------
xpos db 0
ypos db 0
hexstr db '0123456789ABCDEF'
outstr16 db '0000', 0 ;register value string
reg16 dw 0 ; pass values to printreg16
msg db "What are you doing, Dave?", 0
times 510-($-$$) db 0
db 0x55
db 0xAA
;==================================
Thank you in advance.
Upvotes: 0
Views: 1592
Reputation: 7844
With multiboot your kernel starts in protected mode, here.
‘CR0’ Bit 31 (PG) must be cleared. Bit 0 (PE) must be set. Other bits are all undefined.
Grub can boot 16-bit kernel because Linux starts in 16-bit here. But it is for the sake of convenience here for Linux, FreeBSD, NetBSD and OpenBSD. And here
Operating systems that do not support Multiboot and do not have specific support in GRUB (specific support is available for Linux, FreeBSD, NetBSD and OpenBSD) must be chain-loaded, which involves loading another boot loader and jumping to it in real mode.
Upvotes: 1
Reputation: 18521
If you want to write a real mode kernel (16-bit) then you cannot use GRUB. GRUB can only load 32-bit kernels.
You should think about the fact that BIOS interrupts cannot be used that simply in 32-bit mode.
The MultiBoot specification (http://www.uruk.org/orig-grub/boot-proposal.html) describes the file format required for GRUB.
Definitely this is nothing for beginners...
If you want to boot a kernel without GRUB (and your OS is larger than 510 bytes) your boot sector must load the rest of the OS from the disk using interrupt 0x13.
At this time the computer runs in 16-bit real mode.
Upvotes: 1