如何在汇编语言中打印字符串

6
我正在尝试使用NASM在Q模拟器中打印一个字符串。我的代码如下:
mov bx,HELLO
mov ah, 0x0e
int 0x10
HELLO:
  db 'Hello', 0
jmp $
times 510-($-$$) db 0
dw 0xaa55

然而,当我编译这段代码时,得到的输出是:
UU

请问有人能告诉我为什么会这样吗?如何获得所需的字符串输出?

提前致谢。


2
你没有展示如何组装它,但有一件事引起了我的注意,那就是你在顶部没有一个ORG指令,像 ORG 0x7c00。可能你在使用_NASM_进行汇编时使用了"-f bin",并且它使用了默认的ORG值0x0000。虽然这不会是你的问题。Int 10h/ah = 0eh逐个字符打印,并且不接受_BX_中的内存地址。 - Michael Petch
是的,这是一个测试程序。实际上,我正在努力理解如何调用宏,但无法正确运行此代码。在使用NASM汇编时,我使用了"-f bin"选项。 - Sanket Gupte
1
你还应该在 jmp $ 之后放置你的数据。如果将其放在 JMP 之前,处理器将解码 HELLO 中的数据作为指令,可能会导致意外行为。 - Michael Petch
2
如果您希望使用int 0x10h/0eh打印字符串,则必须逐个字符地执行。本教程中的“print_string”可能会有所帮助:http://mikeos.sourceforge.net/write-your-own-os.html - Michael Petch
我也试过那个,Michael,但是没有成功。 - Sanket Gupte
2
如果您尝试像这个例子一样完整的示例:http://www.capp-sysware.com/misc/stackoverflow/40143596/boot.asm,会发生什么?这将设置一个堆栈,适当地初始化ES和DS,并创建一个“_print_string”函数,该函数通过使用INT 10h / AH = 0eh循环遍历空终止字符串并逐个打印每个字符。 - Michael Petch
2个回答

4

好的,这里有一个关于你问题的方法。

为了加载字符串,必须将其移动到 si 中(不需要太深入地解释,请按照步骤操作)。接下来,为了将字符加载到寄存器AL中,使用 lodsb 。然后,我们必须打印它,所以使用 int 10h mov ah,0Eh 。Int 10h处理视频,ah告诉BIOS打印我们在al中拥有的任何内容(也就是lodsb)。接下来,我们必须有一个结束加载字符,以免无限循环。我个人使用 0x00 ,但你可以使用0。在我的情况下,0x00更好,因为不仅可以使用0,而且0x00不会打印任何内容,所以你永远不需要它。

好的,我们已经完成所有任务,以下是代码:

    mov si, message       ;消息位置*你可以更改*
    call print            ;调用并在执行完成后返回
print: mov ah, 0Eh ;设置函数
.run: lodsb ;获取字符 ; cmp al, 0x00 ;我会使用这个,但是你不需要使用,所以使用: cmp al, 0 ;0的十六进制码为0x48,因此它不是0x00 je .done ;如果找到结束代码,则跳转到.done int 10h ;否则打印 jmp .run ;并返回.run
.done: ret ;返回
message db 'Hello, world', 0 ;如果你使用0x00 ;message db 'Hello, world', 0x00

3
0(十进制)和 0x00(十六进制)是同一个数字。 '0' 是在 NASM 语法中写 480x30 的一种方式,也许这就是你在撰写关于 00x00 差异的评论时所思考的内容?是的,'0' 将会是一个糟糕的终止符选择,但是使用 0 则完全正常。请注意它位于引用的字符串外面,因此只是一个数字。 - Peter Cordes
3
使用lodsb是循环遍历字符串的一种方式;如果您选择这种方式,那么您需要使用指向DS:SI的指针(https://www.felixcloutier.com/x86/lods:lodsb:lodsw:lodsd:lodsq),并将DS设置为与ORG设置匹配(在引导加载程序中,BIOS并不总是为您设置正确的DS值;在不同的计算机上可能存在多个不同的DS值,因此您应该在传统BIOS引导加载程序中自己设置DS值,就像问题所描述的一样)。 - Peter Cordes
@Logan Rios,只有在用撇号括起来时,0才被定义为0x48(ASCII十六进制值),因为汇编器会将其视为字符串而不是十六进制值。 - FryingRonald

-2

我从这里找到了这段代码,它对我很有用。使用nasm编译成二进制文件,然后将.flp文件作为引导信息并启动它。希望它对你也有用。


1
Stack Overflow的答案应该是自包含的,即使链接失效也至少有一定的用处。但这里并非如此;您可以通过编辑来包含一些代码和/或解释如何设置ds以匹配ORG并循环遍历字符串来修复它。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接