I don't know if it's a good idea, at least aesthetically, to post all the code here. But i'll do since it's not very long. Perhaps some one can give it a try (with MINGW please).
the boot sector source code: boot.asm
Code:
[ bits 16]
[org 0x7c00]
KERNEL_OFFSET equ 0x1000
mov [BOOT_DRIVE], dl
mov bp, 0x9000
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
;load_kernel:
mov bx, MSG_LOAD_KERNEL
call print_string
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, [BOOT_DRIVE]
call disk_load
call switch_to_pm
jmp $
;==============
print_string:
mov ah, 0x0e
loop:
mov al, [bx]
cmp al, 0
je out
int 0x10
add bx, 0x01
jmp loop
out:
mov al, ' '
int 0x10
ret
;====================
disk_load:
push dx
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02
int 0x13
jc disk_error
pop dx
cmp dh, al
jne disk_error
ret
disk_error:
mov bx, [DISK_ERROR_MSG]
call print_string
jmp $
DISK_ERROR_MSG:
db 'Disk read Error!', 0
;=======
switch_to_pm:
cli
lgdt [gdt_descriptor]
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:init_pm
[bits 32]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
mov ebx, MSG_PROT_MODE
call print_string_pm
call KERNEL_OFFSET
jmp $
;=================
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
print_string_pm:
pusha
mov edx, VIDEO_MEMORY
print_string_pm_loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je done
mov [edx], ax
add edx, 2
add ebx, 1
jmp print_string_pm_loop
done:
popa
ret
;===================
; GDT tabel
gdt_start:
dd 0x0
dd 0x0
gdt_code:
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
gdt_data:
dw 0xffff
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
BOOT_DRIVE:
db 0
MSG_REAL_MODE:
db " Started in 16- bit Real Mode ", 0
MSG_PROT_MODE:
db " Successfully landed in 32- bit Protected Mode ", 0
MSG_LOAD_KERNEL:
db " Loading kernel into memory. ", 0
times 510-($-$$) db 0
dw 0xaa55
the kernel entry point "kernel_entry.asm" :
Code:
[bits 32]
[extern _kmain]
call _kmain
jmp $
NOTE the underscore and the name of the main function it must be different than "main" else the linker will be unhappy!
The kernel source code "kernel.c":
Code:
void kmain(void)
{
const char *str = "Hello World!!";
char *vidmem = (char*)0xb8000;
unsigned int i;
// print char 'A' OK
*vidmem ='A';
*(vidmem+1) =0xA5;
// first version to print the string NOT OK
for(i=0;;i++){
if(str[i]==0) break;
*vidmem =str[i];
*(vidmem+1) =0xA5;
vidmem+=2;
}
// second version to print the string NOT OK
while(*str != 0) {
*vidmem= *str;
vidmem+=2;
str++;
}
// print char 'M' on the next line OK
vidmem +=160;
*vidmem ='M';
*(vidmem+1) =0xA5;
for(;;);
}
And last the makefile:
Code:
# Default make target
all: os.img
# Build the os image
os.img: boot.bin kernel.bin
cat boot.bin kernel.bin > os.img
# Build the kernel binary
kernel.bin: kernel_entry.o kernel.o
ld -T NUL -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o
objcopy -O binary -j .text kernel.tmp kernel.bin
# Build the kernel object file
kernel.O: kernel.C
gcc -ffreestanding -c kernel.c -o kernel.o
# Build the kernel entry object file
kernel_entry.o: kernel_entry.asm
nasm kernel_entry.asm -f elf -o kernel_entry.o
# Build the boot binary
boot.bin: boot.asm
nasm -f bin -o boot.bin boot.asm
clean:
rm -f *.o *.tmp *.bin
the command :
ld -o kernel.bin -Ttext 0x1000 kernel.o --oformat binary
didn't work for me !!