What about this code, does this work?
boot.asm:
Code: Select all
[BITS 16]
global test_var
extern _start
jmp start
start:
; Segments initialization at 0x0000:0x07C00
mov ax, 0x0000
mov ds, ax
mov es, ax
jmp 0x0000:begin ; set CS to 0x0000 and IP to 0x7Cxx
begin:
; Stack from 0x8F000 to 0x80000
mov ax, 0x8000
mov ss, ax
mov sp, 0xf000
nop
;readSectors 0x100, 5, 2
pusha
mov ah, 02h
mov al, 15
mov ch, 0
mov cl, 2
mov dh, 0
mov bx, 0x0000
mov es, bx
mov bx, 0x7E00
int 0x13
popa
; ------------------------------------
; Prepare to switch to protected mode
; ------------------------------------
; Compute the limit (=GDT size)
mov ax, gdtend
mov bx, gdt
sub ax, bx ; Compute the difference between the first data and the last data of the GDT (gdtend - gdt)
mov word [gdt_struct], ax ; Store the result in the first field of the structure
; Compute the base (compute the physical address)
xor eax, eax ; Set EAX to 0
xor ebx, ebx ; Set EBX to 0
mov ax, ds ; Store the data segment value in AX
mov ecx, eax ; Store it in ECX via EAX
shl ecx, 4 ; Shift the value in ECX left 4 bits (the same as multiplying it by 16)
mov bx, gdt ; Store label "gdt" address in BX
add ecx, ebx ; Add data segment address and label "gdt" address
mov dword [gdt_struct+2], ecx ; Store the result in the second field of the structure
; ------------------------------------
; Switch to protected mode
; ------------------------------------
cli ; Disable interrupts because they won't be valid anymore
; after switching to protected mode
lgdt [gdt_struct] ; Load the GDT in GDTR register, to indicate to the CPU
; where is located the GDT
mov eax, cr0
or ax, 1
mov cr0, eax ; Set the "PE" (Protection Enable) bit in CR0 register
jmp run_kernel
run_kernel:
mov ax, 0x10 ; Initialize data segments to data selector (0x10)
mov ds, ax
mov cx, ax
mov fs, ax
mov gs, ax
mov es, ax
mov ss, ax
mov esp, 0x9F000
; Jump to the kernel
jmp dword 0x8:0x7E00
test_var: dd 11
msg_reading_error: db "Error by reading on the floppy disk.", 13, 10, 0
msg_reboot: db "Press a key to restart the computer", 13, 10, 0
bootdisk: db 0
; GDT Descriptors for code segment and data segment
gdt: ; NULL descriptor
db 0, 0, 0, 0, 0, 0, 0, 0
gdt_cs: ; Code segment descriptor
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
gdt_ds: ; Data segment descriptor
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
gdtend: ; Indicate the end of the table (useful to compute the limit)
; Structure containing the limit and the base of the GDT, which have to be loaded in the GDTR register (via "lgdt" instruction)
gdt_struct:
dw 0 ; Limit
dd 0 ; Base
; Fill the remaining bytes with 0 (to have 512 bytes in total)
times 510-($-$$) db 0
dw 0xAA55 ; Boot signature: so that the bios recognize it as bootable
kernel.c:
Code: Select all
#define SCREEN_WIDTH 80
#define SCREEN_HEIGHT 25
asm("jmp _start");
typedef unsigned int size_t;
char* vidmem=(char*)0xb8000;
int cursorX, cursorY = 0;
void itoa(char *buf, unsigned long int n, int base)
{
unsigned long int tmp;
int i, j;
tmp = n;
i = 0;
do {
tmp = n%base;
buf[i++] = (tmp < 10) ? (tmp + '0') : (tmp + 'a' - 10);
} while (n /= base);
buf[i--] = 0;
for (j=0; j<i; j++, i--) {
tmp = buf[j];
buf[j] = buf[i];
buf[i] = tmp;
}
}
void putchr(char character)
{
size_t index = (cursorY * SCREEN_WIDTH + cursorX)*2;
vidmem[index] = character;
vidmem[index+1] = 0x07;
if(++cursorX == SCREEN_WIDTH)
{
cursorX = 0;
cursorY++;
}
}
size_t strlen(const char* str)
{
size_t ret = 0;
while ( str[ret] != 0 )
ret++;
return ret;
}
void print(const char* string)
{
size_t size = strlen(string);
size_t i = 0;
for (i; i < size; i++)
putchr(string[i]);
}
int _start()
{
//asm("movb $0, %ah; movb $3, %al; int $0x10");
print("Hello");
extern unsigned long int test_var;
char test[20];
itoa(test, test_var, 10);
print(test);
while(1);
}
Makefile:
Code: Select all
MM=-m32 -march=i686 -mtune=generic
all:
nasm -f elf32 boot.asm -o boot.elf
gcc $(MM) -c kernel.c -o kernel.o
gcc $(MM) -nostartfiles -nostdlib -nodefaultlibs -Xlinker \
--oformat=binary -Xlinker -Ttext -Xlinker 0x7C00 \
-o test.bin boot.elf kernel.o
dd if=/dev/zero of=dumpsect.bin count=1 bs=512
cat test.bin dumpsect.bin > test2.bin
qemu-system-i386 -boot a -fda test2.bin