String 不使用预定义函数在程序集中打印字符串
我必须在汇编中定义一个函数,该函数允许我循环使用声明的字节字符串,并使用BIOS中断打印它们。我处于16位实模式。这是一个关于从教科书中编写一个小引导程序的练习,但它似乎只是一个草稿,缺少了一些东西。 我已获得以下代码: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
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在那一行给出了一个编译错误(无效的有效地址)。