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

时间:2017-11-10 15:37:09

标签: assembly nasm x86-16

我正在尝试以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

提前致谢,如果再一次这是一个糟糕的问题,我很抱歉。

1 个答案:

答案 0 :(得分:4)

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

查看代码有几件事情不对,例如:

mov ds, [INPUT_STRING]

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

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

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

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

mov si, INPUT_STRING
mov di, shut_msg

您正在使用cx加载0xFFFF

mov cx, 0xFFFF

为什么呢?字符串恰好是0xFFFF字节长吗?如果不是,你将比不仅仅是字符串的长度而得到一个虚假的结果。

总结:

  • 您需要了解分段寻址模型以及分段寄存器的用途
  • 你需要理解字符串值和字符串指针之间的区别,以及值和指针之间的区别
  • 您需要了解字符串在内存中的存储方式
  • 您需要阅读并理解指令行为/语义