Jiří Velek
Jiří Velek

Reputation: 165

Printing characters to screen ASM in protected mode

I'm trying to enter the protected mode and then print out "Hi"

But instead it just prints "Loading OS" from my bios interrupt call (which happened before entering pmode) And nothing else.

My Bootloader.asm

%DEFINE KERNEL_LOAD_OFFSET 0x1000

org 0x7c00

bits 16

xor ax, ax
mov ds, ax

start: jmp main

Print:
 .print:
  lodsb
  or al, al
  je .done

  mov ah, 0x0E
  int 0x10

  .repeat:
   jmp .print

 .done:
  ret

ResetFloppy:
 mov ah, 0x0

 int 0x13
 jc ErrorFloppy
 .done:
  ret

ReadFloppy:

 mov ah, 0x02
 int 0x13

 jc ErrorFloppy

 .done:
  ret

ErrorFloppy:

 mov si, msgErrorFloppy
 call Print

 jmp hang


main: 
 .print:

  mov si, msg
  call Print

 .loadFile:
  mov al, 0xF
  mov ch, 0x0
  mov cl, 0x02
  mov dh, 0x0
  mov dl, 0x0
  mov bx, KERNEL_LOAD_OFFSET

  call ResetFloppy
  call ReadFloppy


 .loadGDT:
   lgdt [gdtr]
 .pM_start:
  cli
  pusha

  mov eax, cr0
  or al, 1
  mov cr0, eax

  popa

  jmp 0x08:ljmp_pM


 bits 32
 ljmp_pM: 
  mov ax, 0x10
  mov ds, ax
  mov ss, ax
  mov fs, ax
  mov es, ax
  mov gs, ax

  jmp KERNEL_LOAD_OFFSET

hang:
 jmp $

gdt:
NULL_DESC:
    dd 0            ; null descriptor
    dd 0

CODE_DESC:
    dw 0xFFFF       ; limit low
    dw 0            ; base low
    db 0            ; base middle
    db 10011010b    ; access
    db 11001111b    ; granularity
    db 0            ; base high

DATA_DESC:
    dw 0xFFFF       ; data descriptor
    dw 0            ; limit low
    db 0            ; base low
    db 10010010b    ; access
    db 11001111b    ; granularity
    db 0            ; base high

gdtr:
    Limit dw 24         ; length of GDT
    Base dd NULL_DESC   ; base of GDT

msg db "Loading OS", 13, 10, 0
msgErrorFloppy db "There was an error with the floppy", 13, 10, 0

FILL:
 times 510-($-$$) db 0

BOOTSECTOR:
 dw 0xAA55

Kernel.asm

bits 32

mov dword [0xB8000], 0x07690748

jmp $

And Compile.bat

nasm -f bin Dev/BootLoader.asm -o Bin/BootLoader.bin
nasm -f bin Dev/Kernel.asm -o Bin/Kernel.bin

dd if=Bin/BootLoader.bin of=Image/Image.img seek=0
dd if=Bin/Kernel.bin of=Image/Image.img seek=1 conv=notrunc

pause

I use bochs. And all I get is this: http://prntscr.com/d24wmm

Upvotes: 4

Views: 3364

Answers (1)

TravorLZH
TravorLZH

Reputation: 302

In 32-bit protected mode, you are not able to use BIOS because it's written in 16-bit real mode's code. So, you have to access the video memory like this:

    mov ebx,0xb8000    ; The video address
    mov al,'!'         ; The character to be print
    mov ah,0x0F        ; The color: white(F) on black(0)
    mov [ebx],ax        ; Put the character into the video memory

Then you may see a ! in the beginning of the screen. If you want to just print at the cursor position, you can get the cursor offset like this:

    mov dx,0x3D4       ; Tell the control I/O port to get the lower byte of
    mov al,0x0F        ; the cursor offset
    out dx,al
    mov dx,0x3D5       ; Switch to data I/O port
    in  al,dx          ; Get the cursor offset's lower byte

    mov dx,0x3D5       ; Tell the control I/O port to get the higher byte of
    mov al,0x0E        ; the cursor offset
    out dx,al
    mov dx,0x3D5       ; Switch to data I/O port
    in  al,dx          ; Get the higher byte

    imul ax,2           ; Because a character in video memory costs 2 bytes
                       ; (i.e character and attribute), we need to twice the cursor offset

In 32-bit protected mode, to increase your code's efficiency, you could use some high-level language like C to create the functions. This really increased the readability of the code.

Upvotes: 2

Related Questions