Printing a string in assembly using no predefined function

别等时光非礼了梦想. 提交于 2019-12-07 20:50:15

问题


I have to define a function in assembly that will allow me to loop through a string of declared bytes and print them using a BIOS interrupt. I'm in 16 bit real mode. This is an exercise on writing a little bootloader from a textbook, but it seems that it was only a draft and it's missing some stuff. I have been given the following code:

org 0x7c00

mov bx, HELLO_MSG
call print_string

mov bx, GOODBYE_MSG
call print_string

jmp $                ;hang so we can see the message

%include "print_string.asm"

HELLO_MSG:
    db 'Hello, World!', 0

GOODBYE_MSG:
    db 'Goodbye!', 0

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

My print_string.asm looks like this:

print_string:
    pusha
    mov ah, 0x0e

    loop:
        mov al, bl
        cmp al, 0
        je return
        int 0x10
        inc bx
        jmp loop

    return:
        popa
        ret

I have some idea of what I'm doing, but the book doesn't explain how to iterate through something. I know how to do it in C but this is my first time using assembly for something other than debugging C code. What happens when I boot through the emulator is that it prints out a couple of lines of gibberish and eventually hangs there for me to see my failure in all it's glory. Hahaha.


回答1:


Well, it looks like it loads the address of the string into the BX register before calling the function.

The actual function looks like it is trying to loop through the string, using BX as a pointer and incrementing it (inc bx) until it hits the ASCII NUL at the end of the string (cmp al, 0; je return)...

...but something is wrong. The "mov al, bl" instruction does not look correct, because that would move the low 8 bits of the address into al to be compared for an ASCII NUL, which does not make a lot of sense. I think it should be something more like "mov al, [bx]"; i.e. move the byte referenced by the BX address into the AL register -- although it has been a long time since I've worked with assembly so I might not have the syntax correct.

Because of that bug, the 10h interrupt would also be printing random characters based on the address of the string rather than the contents of the string. That would explain the gibberish you're seeing.




回答2:


I think the issue is you cannot count on the int preserving any of your registers, so you need to protect them. Plus, what Steven pointed out regarding loading of your string address:

; Print the string whose address is in `bx`, segment `ds`
; String is zero terminated
;
print_string:
    pusha

loop:
    mov   al, [bx]    ; load what `bx` points to
    cmp   al, 0
    je    return
    push  bx          ; save bx
    mov   ah, 0x0e    ; load this every time through the loop
                      ; you don't know if `int` preserves it
    int   0x10
    pop   bx          ; restore bx
    inc   bx
    jmp   loop

return:
    popa
    ret


来源:https://stackoverflow.com/questions/18731047/printing-a-string-in-assembly-using-no-predefined-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!