为什么 `cmpsb` 似乎不比较寄存器的值?

Why does `cmpsb` not seem to compare the values of registers?

我正在尝试在 16 位实模式下编写 DOS 克隆,虽然一旦我完成当前问题,我可能只学习 32 位汇编。我的问题过去一直被否定,但这是最后一次,恐怕我确实需要咨询这个网站。改进了我之前的问题,我付出了更多的努力来了解更多关于汇编代码中的指针和堆栈的信息。
显然,指令 cmpsb 比较两个字符串,分别位于 ESDS 中。我正在尝试将 INPUT_STRING 的值移动到 DS 并将 shutmsg 的值移动到 ES ,这似乎是正确的寄存器(这些是之前声明的变量)。我的指令看起来没问题,它们编译得很好,但是当我输入 shutdown 时它不起作用,当我通过 GDB 运行 它时,它只显示

0x0000fff0 in ?? ()

我不知道怎么了。我真的不知道。这是我的代码:

prompts:
    mov si, prompt
    call prints
    call scans
    push ds
    mov ds, [INPUT_STRING]
    mov es, [shutmsg]  
    mov cx, 0xFFFF
    cld
    repe cmpsb
    pop ds
    je shutdown
    mov si, newline
    call prints
    mov si, INPUT_STRING
    call prints
    mov si, newline
    call prints
    jmp prompts

提前致谢,如果这又是一个糟糕的问题,我们深表歉意。

实际上cmpsb比较的是ES:DIDS:SI分别指向的两个字符串。 ES:DI 是指寄存器对 ESDI,其中 ES 将保存段地址,而 DI 将保存偏移地址。 (你懂分段寻址吗?从你的问题看不清楚)

查看你的代码有几处不对,例如:

mov ds, [INPUT_STRING]

... 会将内存位置 INPUT_STRING 中的值加载到 ds 寄存器中。首先,从你的问题中不清楚 INPUT_STRING 是否真的包含指向字符串或字符串本身的指针,但我怀疑(根据你的后续代码)它是字符串本身的位置。所以,你不仅加载了错误的值,而且你只加载了 ds 而不是 si.

将正确的值加载到 ds 取决于字符串的段地址,这在问题中并不明显(因此很难为您提供有用的建议)。如果与代码段相同,可能是小程序,可以将esds设为与cs相同的值,如:

mov ax, cs
mov ds, ax
mov es, ax

(但同样,这只是一个示例。正确的解决方案取决于您的其余代码)。然后您需要加载 sidi 寄存器:

mov si, INPUT_STRING
mov di, shut_msg

您正在加载 cx 0xFFFF:

mov cx, 0xFFFF

为什么?字符串的长度是否恰好为 0xFFFF 字节?否则,您不仅会比较字符串的长度,还会得到虚假的结果。

总结:

  • 您需要了解分段寻址模型以及段寄存器的用途
  • 您需要了解字符串值和字符串指针之间的区别,以及值和指针之间的一般区别
  • 您需要了解字符串在内存中的存储方式
  • 您需要阅读并理解说明behaviour/semantics