-2

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.

Jester
  • 56,577
  • 4
  • 81
  • 125
RadoslavL
  • 56
  • 6
  • 2
    If you get an invalid operands error consult the manual about what operands are valid. You will see `cmp` does not take two memory operands. You will have to go through a register, e.g. `mov al, [di]; cmp al, [bx]`. As for the other, you did not specify operand size so the assembler does not know what you want. Use `cmp byte [bx], 0` – Jester Feb 26 '23 at 19:12
  • @Jester Thanks for the explanation! I didn't know that `cmp` didn't take two memory operands. Feel free to add this as an answer! – RadoslavL Feb 26 '23 at 19:14

1 Answers1

2

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.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • 1
    Note that using `cmpsb` will also use `es` segment so that needs to be set up properly. – Jester Feb 26 '23 at 21:54
  • I used `cmp di, si` to compare the addresses of the two strings, because they are the same string. I think it does not make sense to put a 0 at the end of the string, as that will cost one more loop iteration and wouldn't change a thing. The code is simply looping through it and checking if the loop has reached the end of the string (the end address would match the current address). – RadoslavL Feb 27 '23 at 07:56
  • @Sep: There's a canonical duplicate for attempts to use `cmp mem,mem` - [Why mov/cmp instead of cmp with two memory operands?](https://stackoverflow.com/q/68655052) (which links [What x86 instructions take two (or more) memory operands?](https://stackoverflow.com/q/52573554) for the details of why it's designed that way.) There are a couple other older Q&A's about `cmp` mem,mem as well, but you could link that first one in answers to questions like this. The title question is a duplicate of that so there should be a link somewhere, even if you also answer re: other bugs. – Peter Cordes Feb 28 '23 at 05:59