NASM assembled bootloader memory issue

171 views Asked by At

I am writing a bootloader with nasm. At the moment it is designed to output a welcome string, then record keystrokes while displaying them, printing the stored keystrokes upon finding the enter key, and finally halting.

                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

The program is not functioning as desired. It ceaselessly prints the same character after enter is pressed. How is this error corrected?

1

There are 1 answers

3
Jester On BEST ANSWER

The immediate problem is that your prints destroys bx (because it sets bl and bh) so your printmem loop which requires bx to be preserved blows up.

However, it also destroys al so your input loop won't be storing the correct value in memory to start with, either.

Furthermore, while you want mem to be a pointer to mem + 2, it is actually a pointer to mem + 1 so you overwrite the pointer with the input. Also, you start printing from mem and not mem + 2.

Finally, your input is not terminated by a zero that you are checking for, it's terminated by a 0x0D (the enter).

A working version could be:

                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: Learn to use a debugger.