Hello, I am trying to make a very simple program.
I tried to understand based on this resource:
https://blog.ghaiklor.com/2017/11/02/how-to-implement-a-second-stage-boot-loader/I do not know much about assembly. Note that it may contain partly wrong code. Still, I tested it on qemu.
boot.asm:
[org 0x7c00] ; sets the start address
[bits 16] ; use 16 bits
;; memory offset where our kernel is located
KERNEL_OFFSET equ 0x1000
;; save the boot drive number
mov [BOOT_DRIVE], dl
;; update base and stack pointers
mov bp, 0x9000
mov sp, bp
init:
mov si, msg ; loads the address of "msg" into SI register
mov ah, 0x0e ; sets AH to 0xe (function teletype)
print_char:
lodsb ; loads the current byte from SI into AL and increments the address in SI
cmp al, 0 ; compares AL to zero
je done ; if AL == 0, jump to "done"
int 0x10 ; print to screen using function 0xe of interrupt 0x10
jmp print_char ; repeat with next byte
;; call routine that loads kernel into memory
call load_kernel_into_memory
;; switch to Protected Mode
call switch_to_pm
jmp $
;; routine reads kernel from disk into memory
load_kernel_into_memory:
;; store all register values
pusha
;; set up parameters for disk_read routine
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, [BOOT_DRIVE]
call disk_read
;; restore register values and ret
popa
ret
;
[bits 32]
begin_pm:
;; Check if we can move from Protected Mode to Long Mode
;; If something went wrong (detect_lm shouldn't return at all)
;; we call execute_kernel in x32 Protected Mode
call detect_lm
call execute_kernel
jmp $
[bits 64]
begin_lm:
;; In case, if detect_lm and switch_to_lm works fine, call kernel in x64 mode
call execute_kernel
jmp $
;
execute_kernel:
call KERNEL_OFFSET
jmp $
;
;You can download all full project from the link I provided or you can get it from totorial source page link I added above.
%include "ARMNET/disk/disk_read.asm";
%include "ARMNET/lm/detect_lm.asm";
%include "ARMNET/lm/switch_to_lm.asm";
%include "ARMNET/pm/gdt.asm"
%include "ARMNET/pm/switch_to_pm.asm"
%include "ARMNET/print/print_string.asm";
%include "ARMNET/print/print_nl.asm";
BOOT_DRIVE: db 0
done:
hlt ; stop execution
msg: db "PROGRAM STARTED", 0x0a; we need to explicitely put the zero byte here
;
times 510-($-$$) db 0 ; fill the output file with zeroes until 510 bytes are full
dw 0xaa55 ; magic number that tells the BIOS this is bootable
loader.asmglobal _start
[bits 32]
[extern _kernel_main]
_start:
call [_kernel_main]
jmp $
loader.cextern void kernel_main() {
for (int i = 0; i < 26; i++) {
char c = 0x41 + i;
asm(
"mov %0, %%al;"
"mov $0x0E, %%ah;"
"int $0x10;"
:
: "r" (c)
);
}
}
For "C" link I did:
1)nasm loader.asm -f elf32 -o loader_entry.o
2)gcc -O0 -g -ffreestanding -m32 -c loader.c -o loader.o
3) ld -o "loader.tmp" -m i386pe -Ttext 0x1000 -T NUL loader_entry.o loader.o
4)type boot.bin loader.bin > image.bin
When I test it on qemu I do not see "C" file output.
What I did wrong ?
FILES I ADDED DOES NOT CONTAIN "C". Interestingly, C containing boot works. Prints the text from stage 1. However, not "C" text. Here is the problem. On totorial page, that prints the alphabet. One more point I put _kernel_main and in "C" thats kernel_main otherwise that does not compile.ALL FILES:https://filebin.net/isdh9p2sm29dhgrs
IMAGE-QEMU-OUTPUT:https://ibb.co/YyVccGW
I also addet files as attachment.
Thank you.