我正在尝试在 16 位实模式下编写 DOS 克隆,尽管一旦我完成了当前问题,我可能只会学习 32 位汇编。我的问题过去一直受到负面回应,但这是最后一次,恐怕我确实需要咨询这个网站。改进我之前的问题,我付出了更多的努力来了解有关汇编代码中的指针和堆栈的更多信息。
显然,cmpsb
指令比较两个字符串,分别位于 ES
和 DS
中。我正在尝试将 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:DI
和DS:SI
指向的两个字符串。我所说的 ES:DI
是指一对寄存器 ES
和 DI
,其中 ES
将保存段地址, DI
将保存偏移地址。 (你理解分段寻址吗?从你的问题中并不清楚)。
查看您的代码,有几处不正确的地方,例如:
mov ds, [INPUT_STRING]
...会将内存位置 INPUT_STRING 中的值加载到 ds
寄存器中。首先,从您的问题中不清楚 INPUT_STRING
是否确实包含指向字符串或字符串本身的指针,但我怀疑(基于您后续的代码)它是字符串本身的位置。因此,您不仅加载了错误的值,而且只加载了 ds
而不是 si
。
将正确的值加载到ds
取决于字符串的段地址,并且这在问题中并不明显(因此很难为您提供有用的建议)。如果它与代码段相同(这可能是小程序),则可以将 es
和 ds
设置为与 cs
相同的值,类似:
mov ax, cs
mov ds, ax
mov es, ax
(但是,这只是一个示例。正确的解决方案取决于代码的其余部分)。然后,您需要加载 si
和 di
寄存器:
mov si, INPUT_STRING
mov di, shut_msg
您正在使用 0xFFFF
加载 cx
:
mov cx, 0xFFFF
为什么?字符串的长度是否正好为 0xFFFF 字节?如果不是,您将不仅仅比较字符串的长度并得到虚假结果。
总结:
- 您需要了解分段寻址模型以及段寄存器的用途
- 您需要了解字符串值和字符串指针之间的区别,以及值和指针之间的一般区别
- 您需要了解字符串在内存中的存储方式
- 您需要阅读并理解指令行为/语义
关于assembly - 为什么 `cmpsb`似乎没有比较寄存器的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47226326/