【问题标题】:x86 CMP instruction not working for a single word comparisonx86 CMP 指令不适用于单字比较
【发布时间】: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_MSGGOODBYE_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


【解决方案1】:

CMP 指令不能用于单字比较的原因是一个字必须包含 2 个字节。由于编译后的输出显示两条消息之间只有 1 个字节,因此您需要将 CMP 指令的大小从字更改为字节:

cmp byte [bx], 0

我错误地假设编译后的输出格式将字节排列为 2。但是,在 Michael Petch 的以下评论的帮助下:

第 4 行以 00 47 6f 开始,这些值中的每一个(由空格分隔)都是一个字节,而不是 2 个字节。 00 是一个字节的 0,而不是两个字节的 0

我能够意识到我的错误。

【讨论】:

  • ➕1 从错误中学习并回答自己的问题
猜你喜欢
  • 2023-04-02
  • 2012-01-12
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
相关资源
最近更新 更多