我的操作系统显示奇怪的字符

My operating system is showing weird characters

现在我正在用汇编编程我的操作系统,我试图将它加载到闪存驱动器中。但是当我尝试启动操作系统时,它显示奇怪的字符。

汇编代码: 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

这也是我关于堆栈溢出的第一个问题。

How it looks

What it should look like

当引导扇区程序开始时,不能相信段寄存器包含任何特定值。根据你的[org 0x7c00]和你进一步用于寻址内存的指令,DS段寄存器需要包含0。你必须自己设置它:

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

同样,您的程序经常访问堆栈,但您不确定 pre-existing 堆栈是否能胜任该任务。您必须自己设置:

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

BIOS.Teletype 函数 0Eh 已经使用 BLBH 寄存器(它们一起构成 BX)作为它的一些参数。因此,最好使用 SI 寄存器作为您提供给 printf.

的指针

在处理无效答案后,您使用 call wywtd 再次重复。在这种情况下,不 call 而是 jump 更有意义:

jmp wywtd

我不知道这是不是故意的,但是 bm1bm2 消息会在您清屏后立即被删除...

  call reboot

reboot:

这个call reboot是多余的。执行也可以进入 reboot:.

newline:
  mov SI, nl
  call printf
  ret

您可以用跳转 jmp printf.
替换此 so-called 尾调用 但最有效的方法是将 newline 代码直接放在 printf 代码之上。这甚至会削减 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