assembly - C Kernel - Works fine on VM but not actual computer? -
i making basic c kernel. (loaded assembly program) compiling i686-elf cross compiler windows. c code follows:
void cls(); void drawhappy(); void main(){ char *vidptr = (char *)0xb8000; cls(); drawhappy(); } void cls(){ char *vidptr = (char *)0xb8000; unsigned int j = 0; while(j < 80*2*25){ vidptr[j] = ' '; vidptr[j+1] = 0x07; j = j+2; } } void drawhappy(){ char *vidptr = (char *)0xb8000; const unsigned int linewidth = 80*2; vidptr[3] = 0xa7; vidptr[5] = 0xa7; vidptr[7] = 0xa7; vidptr[9] = 0xa7; vidptr[1+linewidth] = 0xa7; vidptr[5+linewidth] = 0xa7; vidptr[7+linewidth] = 0xa7; vidptr[11+linewidth] = 0xa7; vidptr[1+linewidth*2] = 0xa7; vidptr[3+linewidth*2] = 0xa7; vidptr[5+linewidth*2] = 0xa7; vidptr[7+linewidth*2] = 0xa7; vidptr[9+linewidth*2] = 0xa7; vidptr[11+linewidth*2] = 0xa7; vidptr[1+linewidth*3] = 0xa7; vidptr[5+linewidth*3] = 0xa7; vidptr[7+linewidth*3] = 0xa7; vidptr[11+linewidth*3] = 0xa7; vidptr[1+linewidth*4] = 0xa7; vidptr[11+linewidth*4] = 0xa7; vidptr[3+linewidth*5] = 0xa7; vidptr[5+linewidth*5] = 0xa7; vidptr[7+linewidth*5] = 0xa7; vidptr[9+linewidth*5] = 0xa7; } in bochs, gives me expected output:
, if use bootice write bin file boot sector , run vm on virtualbox, works too. if boot usb stick, kinda goes crazy puts weird symbol bottom right corner of screen. (no screenshot because can't) have i7-3770k cpu. why happening?
edit: here's assembly code:
[org 0x7c00] kernel_offset equ 0x1000 mov [boot_drive], dl mov bp, 0x9000 mov sp, bp mov bx, msg_real_mode call print_string call load_kernel call switch_to_pm jmp $ %include "c:/users/aaron/desktop/code_os/print_string.asm" ; load dh sectors es:bx drive dl 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 %include "c:/users/aaron/desktop/code_os/print_string_pm.asm" %include "c:/users/aaron/desktop/code_os/switch_to_pm.asm" ; gdt gdt_start: gdt_null: ; mandatory null descriptor dd 0x0 dd 0x0 gdt_code: ; code segment descriptor dw 0xffff ; limit dw 0x0 ; base 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 [bits 16] load_kernel: mov bx, msg_load_kernel call print_string mov bx, kernel_offset mov dh, 15 mov dl, [boot_drive] call disk_load ret [bits 32] begin_pm: mov ebx, msg_prot_mode call print_string_pm call kernel_offset jmp $ boot_drive db 0 msg_real_mode db 'started in 16-bit real mode',0 msg_prot_mode db 'successfully booted 32-bit protected mode',0 msg_load_kernel db "loading kernel...",0 times 510-($-$$) db 0 ; pad boot sector out zeros dw 0xaa55 ; last 2 bytes form magic number (print-string.asm prints strings, switch_to_pm.asm switches protected mode, , print_string_pm.asm prints strings in protected mode.)
you're not initializing segment registers. try changing start of bootsector this:
xor ax, ax mov bp, 0x9000 mov ds, ax mov es, ax mov ss, ax ; disables interrupts until end of next instruction mov sp, bp mov [boot_drive], dl
Comments
Post a Comment