Search code examples
assemblynasmx86-16biososdev

ASM print function using bios calls


I am trying to add a print function to a ASM kernel that I am writing, though I have tried many with no success. Most, like the one from osdev, simply print out: ?, or two happy faces. I am using the mikeos bootloader and qemu. This is my current kernel, which print out gibberish infinitely:

%include "print.asm"

os_main:
    hello db "Hi!", 0
    mov si, hello
    call print
    jmp $

Contents of print.asm (from a tutorial):

print:
    pusha

; keep this in mind:
; while (string[i] != 0) { print string[i]; i++ }

; the comparison for string end (null byte)
start:
    mov al, [bx] ; 'bx' is the base address for the string
    cmp al, 0 
    je done

    ; the part where we print with the BIOS help
    mov ah, 0x0e
    int 0x10 ; 'al' already contains the char

    ; increment pointer and do next loop
    add bx, 1
    jmp start

done:
    popa
    ret



print_nl:
    pusha
    
    mov ah, 0x0e
    mov al, 0x0a ; newline char
    int 0x10
    mov al, 0x0d ; carriage return
    int 0x10
    
    popa
    ret

What is wrong with this code? I am a new to assembly language, any help would be appreciated.

Assembler: nasm


Solution

  • There are 2 errors in this code.

    os_main:
     hello db "Hi!", 0
     mov si, hello
     call print
     jmp $
    

    You have placed the string at the label hello in the path of the program's execution! The CPU will execute those 4 bytes ("H", "i", "!", 0) as if they represented instructions. Obviously they aren't. Hence the output of gibberish.

    This will work:

    os_main:
     mov si, hello
     call print
     jmp $
     hello db "Hi!", 0
    

    Like fuz wrote in a comment, the print code is wrong in that it uses the wrong address register (BX) to match your call (SI).

    Better use next code:

    ; IN (si) OUT ()
    print:
        pusha
        mov  bx, 0007h   ; BH is DisplayPage, BL is GraphicsColor
      start:
        mov  al, [si]    ; <<<<<<<<<
        cmp  al, 0 
        je   done
        mov  ah, 0x0E    ; BIOS.Teletype
        int  0x10
        inc  si          ; <<<<<<<<<
        jmp  start
      done:
        popa
        ret
    
    ; IN () OUT ()
    print_nl:
        pusha
        mov  bh, 0       ; BH is DisplayPage (No need for GraphicsColor in BL)
        mov  ax, 0x0E0D  ; BIOS.Teletype CR
        int  0x10
        mov  ax, 0x0E0A  ; BIOS.Teletype LF
        int  0x10
        popa
        ret