【发布时间】:2017-09-24 14:51:09
【问题描述】:
在比较单个字(2 个字节)时,我遇到了 CMP 指令的问题。
以下是我的main.asm:
[org 0x7c00]
mov bx, HELLO_MSG
call print_string
mov bx, GOODBYE_MSG
call print_string
jmp $
%include "print_string.asm"
; Data
HELLO_MSG:
db 'Hello, World!', 0
GOODBYE_MSG:
db 'Goodbye!', 0
这是 print_string.asm 文件:
print_string:
pusha
mov ah, 0x0e
loop:
call print_char
cmp word [bx], 0
jne loop
popa
ret
print_char:
mov al, [bx]
int 0x10
add bx, 1
ret
此代码打印出以下内容:
世界你好!再见!再见!
我知道当我添加时
db 0
在 HELLO_MSG 和 GOODBYE_MSG 之间,代码将按预期工作。谁能解释为什么CMP 仅在字符串之间有 4 个字节的 0 时才有效?
如果有人有兴趣查看编译后的输出,这里是:
bb 23 7c e8 08 00 bb 31 7c e8 02 00 eb fe 60 b4
0e e8 07 00 83 3f 00 75 f8 61 c3 8a 07 cd 10 83
c3 01 c3 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21
00 47 6f 6f 64 62 79 65 21 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa
末尾的55 aa 是我添加的,因为我将此代码用作引导加载程序。
【问题讨论】:
-
你正在做
cmp word [bx],0比较从地址bx开始的 2 个字节。您可能想要比较单个字节。cmp byte [bx],0 -
我还建议您正确设置段寄存器和堆栈等。我在此 Stackoverflow 答案中给出了一些提示,其中包含 general bootloader tips
-
您可能还想为
print_string使用除BX 之外的寄存器。 Int 10/AH=0Eh 使用 BH 作为要写入的页码。您可能希望将其设置为 0。这意味着您应该使用 BX 以外的寄存器作为字符串指针。也许SI代替。 -
QEMU 不能很好地进行实模式调试(它使用了并非专为实模式设计的 GDB)。 BOCHS 有一个非常适合调试引导加载程序的内部调试器。所以是的,他们做同样的事情,但是一个工具比调试器要好得多,它可以帮助你找到像我第一条评论中的问题。
-
第 4 行以
00 47 6f开头,每个值(由空格分隔)都是一个字节,而不是 2 个字节。00是一个字节的 0,而不是两个字节的 0
标签: assembly x86 x86-16 qemu bootloader