英文:
"error: invalid combination of opcode and operands", when comparing "dereferenced" addresses
问题
我编写了这段代码,用于比较两个字符串,并在代码字符串相同时打印string2
:
enter:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
mov di, reserved_string
mov bx, string2
jmp loop1
loop1:
cmp di, si
je middle_loop1
cmp [di], [bx] ; 错误:操作码和操作数的组合无效
jne go_back_loop1
inc di
inc bx
jmp loop1
go_back_loop1:
mov si, reserved_string
jmp key_press
middle_loop1:
mov bx, string2
pusha
jmp print_ping
print_ping:
cmp [bx], 0 ; 错误:未指定操作大小
je go_back_print_ping
mov ah, 0x0e
mov al, [bx]
int 0x10
inc bx
jmp print_ping
go_back_print_ping:
popa
jmp key_press
它无法编译,我得到了有关两行的错误。我不知道如何解决第一个问题,因为我应该能够比较这两个值。
已解决:该指令不支持两个解引用地址。
英文:
I wrote this code to compare two strings and print string2
, if the code strings are the same:
enter:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
mov di, reserved_string
mov bx, string2
jmp loop1
loop1:
cmp di, si
je middle_loop1
cmp [di], [bx] ; error: invalid combination of opcode and operands
jne go_back_loop1
inc di
inc bx
jmp loop1
go_back_loop1:
mov si, reserved_string
jmp key_press
middle_loop1:
mov bx, string2
pusha
jmp print_ping
print_ping:
cmp [bx], 0 ; error: operation size not specified
je go_back_print_ping
mov ah, 0x0e
mov al, [bx]
int 0x10
inc bx
jmp print_ping
go_back_print_ping:
popa
jmp key_press
It does not compile and I get errors about two of the lines. I don't know how to fix the first problem, as I should be able to compare the two values.
Solved: The instruction does not support two dereferenced addresses.
答案1
得分: 2
不会编译。
> cmp [di], [bx] ; 错误:操作码和操作数的组合无效
cmp
指令不允许有两个内存操作数。如 @Jester 在评论中建议的,你可以这样写:
mov al, [di]
cmp al, [bx]
jne go_back_loop1
或者,你可以使用 cmpsb
指令。它只需要使用 SI 寄存器而不是 BX 寄存器,而且不需要指定任何操作数,因为这些是隐含的。另外,如果还没有这样做的话,你的代码应该清除方向标志(direction flag)并且 ES 段寄存器应该等于 DS 段寄存器。
cmpsb ; Intel `cmps byte ptr [si], [di]`
jne go_back_loop1
> cmp [bx], 0 ; 错误:未指定操作大小
在这里,NASM 不知道地址 BX 处的数据是字节(byte)、字(word)还是双字(dword)。你需要明确指定,例如:
cmp byte [bx], 0
有时候你可能有一个寄存器,其值是已知的,比如 CL=0
。那么你可以更短地写上述指令,而且汇编器不会有问题,因为 CL 明确是一个字节:
cmp [bx], cl
现在它可以编译了,但能运行吗?
> loop1:
> cmp di, si
> je middle_loop1
这里的 cmp
比较的是字符串的地址。通常情况下,这些地址总是不同的,并且循环也会同步修改它们。这个 cmp
无法正确结束循环。你需要寻找终止零(terminating zero):
loop1:
mov al, [di]
cmp al, [bx]
jne go_back_loop1 ; 不同
inc di
inc bx
cmp al, 0 ; 终止零
jne loop1
jmp middle_loop1 ; 相同
小心这些。
> jmp loop1
> loop1:
> jmp print_ping
> print_ping:
像这样的跳转是多余的。执行可以直接顺序执行到标记的地址。
英文:
It doesn't compile.
> cmp [di], [bx] ; error: invalid combination of opcode and operands
The cmp
instruction does not allow 2 memory operands. As @Jester proposed in a comment, you could write this as:
mov al, [di]
cmp al, [bx]
jne go_back_loop1
Alternatively, you could use the cmpsb
instruction. It just needs using SI instead of BX, and it does not require mentioning any operands as these are implied. Additionally and if it is not already the case, for your present code the direction flag should be cleared and your ES segment register should be equal to your DS segment register.
cmpsb ; Intel `cmps byte ptr [si], [di]`
jne go_back_loop1
> cmp [bx], 0 ; error: operation size not specified
Here NASM does not know whether the datum at the address BX is a byte, word, or dword. It's your task to specify this as in:
cmp byte [bx], 0
Sometimes it so happens that you have a register with a known value like CL=0
. Then you could write the above shorter and without the assembler complaining because CL is a byte for sure:
cmp [bx], cl
Now it compiles, but will it run?
> loop1:
> cmp di, si
> je middle_loop1
This cmp
compares the addresses of both strings. Normally, these will always be different from each other and the loop also modifies them in sync. This cmp
does not work to end the loop correctly. What you need is looking for the terminating zero:
loop1:
mov al, [di]
cmp al, [bx]
jne go_back_loop1 ; different
inc di
inc bx
cmp al, 0 ; terminating zeroes
jne loop1
jmp middle_loop1 ; identical
Watch out for these.
> jmp loop1
> loop1:
> jmp print_ping
> print_ping:
Jumps like these are redundant. The execution can just fall through in the labeled address.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论