“error: invalid combination of opcode and operands”, 当比较 “解引用” 地址时

huangapple go评论155阅读模式
英文:

"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.

huangapple
  • 本文由 发表于 2023年2月27日 03:10:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75574397.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定