【问题标题】:NASM assembled bootloader memory issueNASM 组装引导加载程序内存问题
【发布时间】:2015-06-20 02:27:23
【问题描述】:

我正在用 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

程序未按预期运行。按下回车后,它不断地打印相同的字符。如何纠正这个错误?

【问题讨论】:

  • mov [mem], cx 在我看来“很有趣”。你打算在那里bx吗?
  • 您忘记指定堆栈段和堆栈指针。
  • @FrankKotler 是的,我的意思是把bx
  • 两个内存转储的差异是预期的。您的代码修改了内存位置.bufqbuf。它们包含用于回车的 ASCII 代码,可能是因为您按下了回车键。您的示例程序没有定义 mem 所以没有汇编。您的程序不一致地使用mem。有时将其视为缓冲区的地址,有时将其视为存储缓冲区地址的地址。
  • @RossRidge 这个想法是[mem]指向内存从[mem + 2]开始

标签: assembly nasm bootloader


【解决方案1】:

直接的问题是您的prints 破坏了bx(因为它设置了blbh),因此需要保留bxprintmem 循环会爆炸。

但是,它也会破坏 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:学习使用调试器。

【讨论】:

  • 为什么字符阅读器需要 pusha/popa?软件中断不保留所有寄存器吗?不移动斧头,1000h;诠释 16 小时; ret 做同样的事情?
  • @Gene 不需要,但我还没有触及那部分代码。我没有优化它,只是修复了错误。
  • 是的,bochs 确实内置了一个简单的调试器。
猜你喜欢
  • 1970-01-01
  • 2021-03-30
  • 2022-01-07
  • 2013-07-07
  • 1970-01-01
  • 2012-04-14
  • 2015-12-20
  • 2011-12-08
相关资源
最近更新 更多