NASM 组装引导程序内存问题

NASM assembled bootloader memory issue

我正在用 nasm 编写引导加载程序。目前设计为输出欢迎字符串,然后在显示时记录击键,在找到回车键时打印存储的击键,最后停止。

                bits       16
                org        0x7C00
start:          jmp        main

bgetkey:        pusha
                mov        ax, 0
                mov        ah, 10h
                int        16h
                mov        [.buf], ax
                popa
                mov        ax, [.buf]
                ret
                .buf       dw 0

prints:         mov        ah, 0x0e
                mov        al, [si]
                cmp        al, 0
                jz         print_end
                mov        bh, 0x00
                mov        bl, 0x07
                int        0x10
                inc        si
                jmp        prints
print_end:      ret

main:           mov        ax, 0x0000           ; set register a
                mov        ds, ax               ; 
                mov        bx, mem
                add        bx, word 1
                mov        word [mem], bx
                mov        si, welcome          ; set and prints
                call       prints               ; 
type:           mov        si, qbuf             ; set prints ptr
                call       bgetkey              ; capture  input
                mov        [qbuf], al           ; set char to sz
                call       prints               ; call print str

                mov        bx, [mem]            ; put chr in mem
                cmp        bx, stop             ; compare loader
                je         oom                  ; end and memory
                mov        byte [bx], al
                add        bx, byte 1
                mov        [mem], bx            ; 

                cmp        byte [qbuf], 0x0D    ; cmpr enter key
                jne        type                 ; continue  next
                mov        si, newline          ; print  newline
                call       prints               ; 

                mov        bx, mem
printmem:       cmp        byte [bx], 0x00      ; check for zero
                je         halt                 ; halt  the  cpu
                mov        cl, [bx]
                mov        byte [qbuf], cl      ; buffer and cpy
                mov        si, qbuf             ; pointer to  si
                call       prints               ; print the char
                inc        bx
                jmp        printmem             ; jump beginning

oom:            mov        si, outomem          ; no more memory
                call       prints               ; print  message

halt:           mov        si, halting          ; cpu is halting
                call       prints               ; print last msg
                hlt                             ; halt  the  cpu

                welcome db "bootloader", 0x0A, 0x0D, 0x00
                newline db 0x0A, 0x00
                outomem db "out of memory", 0x0A, 0x0D, 0x00
                halting db "halting", 0x00
                qbuf       dw 0, 0
                mem        db 0

times 0200h - 2 - ($ - $$)db 0
                stop       dw 0xAA55

该程序未按预期运行。按下回车后,它会不断打印相同的字符。如何更正此错误?

直接的问题是你的 prints 破坏了 bx(因为它设置了 blbh)所以你的 printmem 循环需要 bx被保存起来。

但是,它也会破坏 al,因此您的输入循环也不会在开始时将正确的值存储在内存中。

此外,虽然您希望 mem 成为指向 mem + 2 的指针,但它实际上是指向 mem + 1 的指针,因此您可以用输入覆盖指针。此外,您从 mem 而不是 mem + 2.

开始打印

最后,您的输入不是以您正在检查的零结尾,而是以 0x0D(回车)结尾。

工作版本可以是:

                bits       16
                org        0x7C00
start:          jmp        main

bgetkey:        pusha
                mov        ax, 0
                mov        ah, 10h
                int        16h
                mov        [.buf], ax
                popa
                mov        ax, [.buf]
                ret
                .buf       dw 0

prints:         pusha
.loop:
                mov        ah, 0x0e
                mov        al, [si]
                cmp        al, 0
                jz         print_end
                mov        bh, 0x00
                mov        bl, 0x07
                int        0x10
                inc        si
                jmp        .loop
print_end:      popa
                ret

main:           mov        ax, 0x0000           ; set register a
                mov        ds, ax               ;
                mov        bx, mem
                add        bx, word 2           ; point to after the pointer :)
                mov        word [mem], bx
                mov        si, welcome          ; set and prints
                call       prints               ;
type:           mov        si, qbuf             ; set prints ptr
                call       bgetkey              ; capture  input
                mov        [qbuf], al           ; set char to sz
                call       prints               ; call print str

                mov        bx, [mem]            ; put chr in mem
                cmp        bx, stop             ; compare loader
                je         oom                  ; end and memory
                mov        byte [bx], al
                add        bx, byte 1
                mov        [mem], bx            ;

                cmp        byte [qbuf], 0x0D    ; cmpr enter key
                jne        type                 ; continue  next
                mov        si, newline          ; print  newline
                call       prints               ;

                mov        bx, mem+2            ; start from after the pointer
printmem:       cmp        byte [bx], 0x0D      ; check for end
                je         halt                 ; halt  the  cpu
                mov        cl, [bx]
                mov        byte [qbuf], cl      ; buffer and cpy
                mov        si, qbuf             ; pointer to  si
                call       prints               ; print the char
                inc        bx
                jmp        printmem             ; jump beginning

oom:            mov        si, outomem          ; no more memory
                call       prints               ; print  message

halt:           mov        si, halting          ; cpu is halting
                call       prints               ; print last msg
                hlt                             ; halt  the  cpu

                welcome db "bootloader", 0x0A, 0x0D, 0x00
                newline db 0x0A, 0x00
                outomem db "out of memory", 0x0A, 0x0D, 0x00
                halting db "halting", 0x00
                qbuf       dw 0, 0
                mem        db 0

times 0200h - 2 - ($ - $$)db 0
                stop       dw 0xAA55

PS:学习使用调试器。