Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 不使用预定义函数在程序集中打印字符串_String_Loops_Assembly_X86_Bootloader - Fatal编程技术网

String 不使用预定义函数在程序集中打印字符串

String 不使用预定义函数在程序集中打印字符串,string,loops,assembly,x86,bootloader,String,Loops,Assembly,X86,Bootloader,我必须在汇编中定义一个函数,该函数允许我循环使用声明的字节字符串,并使用BIOS中断打印它们。我处于16位实模式。这是一个关于从教科书中编写一个小引导程序的练习,但它似乎只是一个草稿,缺少了一些东西。 我已获得以下代码: org 0x7c00 mov bx, HELLO_MSG call print_string mov bx, GOODBYE_MSG call print_string jmp $ ;hang so we can see the messag

我必须在汇编中定义一个函数,该函数允许我循环使用声明的字节字符串,并使用BIOS中断打印它们。我处于16位实模式。这是一个关于从教科书中编写一个小引导程序的练习,但它似乎只是一个草稿,缺少了一些东西。 我已获得以下代码:

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
我的print_string.asm如下所示:

print_string:
    pusha
    mov ah, 0x0e

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

    return:
        popa
        ret

我对我正在做的事情有一些想法,但这本书没有解释如何迭代。我知道如何在C中完成这项工作,但这是我第一次将汇编用于调试C代码以外的其他用途。当我通过模拟器引导时,它会打印出几行胡言乱语,最终挂在那里让我看到我的失败。哈哈哈。

看起来它在调用函数之前将字符串的地址加载到BX寄存器中

实际函数看起来像是在尝试循环字符串,使用BX作为指针并递增它(inc BX),直到它到达字符串末尾的ASCII NUL(cmp al,0;je return)

……但有点不对劲。“mov al,bl”指令看起来不正确,因为这会将地址的低位8位移到al中,以便与ASCII NUL进行比较,这没有多大意义。我认为它应该更像是“mov al,[bx]”;i、 e.将BX地址引用的字节移到AL寄存器中——尽管我已经很长时间没有使用汇编了,所以语法可能不正确


由于该缺陷,10h中断还将基于字符串的地址而不是字符串的内容打印随机字符。这就解释了你所看到的胡言乱语。

我认为问题在于你不能指望
int
保存你的任何寄存器,所以你需要保护它们。另外,Steven在加载字符串地址时指出:

; 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

我使用的中断显然保留了寄存器,因为史蒂文的建议奏效了。int 0x10仅查看ax寄存器。但是谢谢你。@Hugo,好的。我仍然认为最好的做法是,除非文档中明确了关于寄存器保存的内容,否则保存您关心的任何寄存器。我在处理不同的int调用时回复了其他人的ASM,在这种情况下,寄存器保存确实是个问题。您在
print_string
例程中勤奋地使用
pusha
popa
这一事实可能也为您节省了这方面的时间。谢谢您的帮助。对于不同的寻址模式是如何工作的,我仍然有点困惑op register'似乎直接使用该值,“op[register]”表示“使用该寄存器中的数字作为要访问的地址”,但我并不完全清楚它。@Steven,巧合的是,我也在使用op使用的同一本书。我也被困在同一件事上,以前也尝试过语法:-
mov al,[bx]
。但是NASM在那一行给出了一个编译错误(无效的有效地址)。