Search code examples
assemblyx86qemubootloader

My operating system is showing weird characters


Now I am programming my operating system in assembly and I tried to load it into flash drive. But when I try to start the operating system, it shows me strange characters.

The assembly code: https://github.com/Zahon7/ZahonOS/blob/main/ZahonOS.asm

[org 0x7c00]

call newline
call newline
call newline
call newline
call newline
call newline
call newline
call newline
call newline
call newline
call newline
call newline

mov bx, bm1
call printf

mov bx, bm2
call printf

call cls

mov bh, 70h
call color

mov bx, welmsg
call printf

wywtd:
    mov bx, welmsg2
    call printf

    call waitforkey

    cmp al, 49
    je reboot

    cmp al, 50
    je guess

    mov bx, invalidmsg
    call printf
    call waitforkey

    call cls

    mov bh, 70h
    call color

    call wywtd

jmp $

good:
    mov bx, okans
    call printf

    call waitforkey
    call reboot

guess:
    call cls

    mov bh, 70h
    call color

    mov bx, gmsg
    call printf

    call waitforkey

    cmp al, 49
    je good

    mov bx, wrongans
    call printf

    call waitforkey
    call reboot

reboot:
    db 0x0ea
    dw 0x0000
    dw 0xffff

newline:
    mov bx, nl
    call printf
    ret

color:
  mov ah, 06h
  xor al, al
  xor cx, cx
  mov dx, 184FH
  ; mov bh, 1Fh
  int 10h
  ret

waitforkey:
  mov ah, 00h
  int 16h
  ret

cls:
  pusha
  mov ah, 0x00
  mov al, 0x03
  int 0x10
  popa
  ret

printf:
  mov ah, 0x0e
  .Loop:
  cmp [bx], byte 0
  je .Exit
    mov al, [bx]
    int 0x10
    inc bx
    jmp .Loop
  .Exit:
  ret

okans: db "Correct answer!", 0x00
wrongans: db "Wrong answer!", 0x00
gmsg: db "What is 78 * 23?", 0x0a, 0x0d, "[1] 1794", 0x0a, 0x0d, "[2] 1894", 0x0a, 0x0d, "[3] 1872", 0x0a, 0x0d, 0x00
invalidmsg: db "Invalid option!", 0x0a, 0x0d, 0x00
nl: db 0x0a, 0x0d, 0x00
welmsg: db "Welcome to ZahonOS Light edition!", 0x0a, 0x0d, 0x00
welmsg2: db "what do you want to do?", 0x0a, 0x0d, "[1] Restart", 0x0a, 0x0d, "[2] Game", 0x0a, 0x0d, 0x0a, 0x0d, "Answer: ", 0x00
bm1: db "Booting ZahonOS Light edition...", 0x0a, 0x0d, 0x00
bm2: db "Done!", 0x00

times 510-($-$$) db 0
dw 0xaa55

Also this is my first question on stack overflow.

How it looks

What it should look like


Solution

  • When a bootsector program begins, the segment registers cannot be trusted to contain any particular value. In accordance with your [org 0x7c00] and the instructions that you further use to address memory, the DS segment register needs to contain 0. You must set it up yourself:

    xor ax, ax
    mov ds, ax
    mov es, ax
    

    Similarly, your program accesses the stack a lot but you don't make sure that the pre-existing stack is up to that task. You must set it up yourself:

    xor ax, ax
    mov ss, ax
    mov sp, 0x7C00    ; Right below the bootsector
    

    The BIOS.Teletype function 0Eh already uses the BL and BH registers (together they form BX) as some of its parameters. Therefore it would be better to use the SI register as the pointer that you provide to your printf.

    At the conclusion of processing an invalid answer you use call wywtd to repeat all over again. It makes more sense to not call but rather jump in this instance:

    jmp wywtd
    

    I don't know if this is on purpose, but the bm1 and bm2 messages are immediately erased by you clearing the screen...

      call reboot
    
    reboot:
    

    This call reboot is redundant. The execution can just as well fall through into reboot:.

    newline:
      mov SI, nl
      call printf
      ret
    

    You could replace this so-called tail call by a jump jmp printf.
    But the most efficient would be to put the newline code directly above the printf code. That would shave off even the jmp printf:

    newline:
      mov SI, nl
    printf:
      ...
    
    [org 0x7c00]
    
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00
    
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    call newline
    
    mov SI, bm1
    call printf
    
    mov SI, bm2
    call printf
    
    call cls
    
    mov bh, 70h
    call color
    
    mov SI, welmsg
    call printf
    
    wywtd:
        mov SI, welmsg2
        call printf
    
        call waitforkey
    
        cmp al, 49
        je reboot
    
        cmp al, 50
        je guess
    
        mov SI, invalidmsg
        call printf
        call waitforkey
    
        call cls
    
        mov bh, 70h
        call color
    
        JMP wywtd
    
    jmp $
    
    good:
        mov SI, okans
        call printf
    
        call waitforkey
        call reboot
    
    guess:
        call cls
    
        mov bh, 70h
        call color
    
        mov SI, gmsg
        call printf
    
        call waitforkey
    
        cmp al, 49
        je good
    
        mov SI, wrongans
        call printf
    
        call waitforkey
    
    reboot:
        db 0x0ea
        dw 0x0000
        dw 0xffff
    
    color:
      mov ah, 06h
      xor al, al
      xor cx, cx
      mov dx, 184FH
      ; mov bh, 1Fh
      int 10h
      ret
    
    waitforkey:
      mov ah, 00h
      int 16h
      ret
    
    cls:
      pusha
      mov ah, 0x00
      mov al, 0x03
      int 0x10
      popa
      ret
    
    newline:
      mov SI, nl
    printf:
      mov ah, 0x0e
      mov bx, 000Fh     ; DisplayPage BH=0, GraphicsColor BL=15 (BrightWhiteOnBlack)
      .Loop:
        mov  al, [SI]
        test al, al
        jz   .Exit
        int  0x10
        inc  SI
        jmp  .Loop
      .Exit:
      ret
    
    okans: db "Correct answer!", 0x00
    wrongans: db "Wrong answer!", 0x00
    gmsg: db "What is 78 * 23?", 0x0a, 0x0d, "[1] 1794", 0x0a, 0x0d, "[2] 1894", 0x0a, 0x0d, "[3] 1872", 0x0a, 0x0d, 0x00
    invalidmsg: db "Invalid option!", 0x0a, 0x0d, 0x00
    nl: db 0x0a, 0x0d, 0x00
    welmsg: db "Welcome to ZahonOS Light edition!", 0x0a, 0x0d, 0x00
    welmsg2: db "what do you want to do?", 0x0a, 0x0d, "[1] Restart", 0x0a, 0x0d, "[2] Game", 0x0a, 0x0d, 0x0a, 0x0d, "Answer: ", 0x00
    bm1: db "Booting ZahonOS Light edition...", 0x0a, 0x0d, 0x00
    bm2: db "Done!", 0x00
    
    times 510-($-$$) db 0
    dw 0xaa55