Search code examples
assemblyx86nasmx86-16

cmps string instruction assembly language 8086


I have a project to make word hunt game in assembly 8088/8086. I am done with everything the only thing remaining is comparing the word the user inputs to the keywords maintained in a variable. now I am using string instruction CMPSB (as both my input and keyword dictionary is in byte) for comparison now in this case it is comparing most of the words correctly but for some reason some words are note identified correctly.

[org 0x0100]
jmp start
str1: db "foe","grim","toll","true","fur"
find: db "grim"


comp:    ;comparison function
push bp
mov bp,sp
pusha

mov cx,18              ;str1 length
lds si,[bp + 4]
les di,[bp + 8]
repne cmpsb            ;compares cx times or until bytes are not equal

popa
pop bp
ret



start:        ;main 
push ds
push str1
push ds
push find
call comp

mov ax,0x4c00
int 21h

in this specific instance this is one of my 5 maintained dictionaries now all the words except true and grim are guessed as i run it on AFD debugger and it does not reduces cx register to 0 which means it has found an instance where both bytes are equal but in case of grim and fur REP uses all of the CX's value. if I change the place of word grim like from second word to first then it is identified correctly but identification of other words suffer this is an example of one dictionary all other 4 dictionaries are on same pattern most words correctly identified few of them are not considered same.


Solution

  • For "foe", "toll", and "fur" will repne cmpsb (RepeatWhileNotEqual) in your current code stop at the arrowed positions, but that doesn't tell you if the whole word is on the list! Just that there was at least 1 matching character.

    foegrimtolltruefur
    foe
    ^
    
    foegrimtolltruefur
    toll
     ^
    
    foegrimtolltruefur
    fur
    ^
    

    To find any of those words completely, you would rather use repe cmpsb (RepeatWhileEqual) and with CX equal to the length of find. You need to repeat the search for any CX-sized part of str1.

    str1: db "foe","grim","toll","true","fur"
    find: db "grim"
    
    comp:
      push bp
      mov  bp, sp
      pusha
      mov  dx, (18 - 4) + 1   ; Possible finds
    next:
      mov  cx, 4
      lds  si, [bp + 4]       ; *find (constant)
      les  di, [bp + 8]       ; *str1 (varying)
      repe cmpsb
      je   found
      inc  word [bp + 8]
      dec  dx
      jnz  next
    notFound:
      ...
    Found:
      ...
    

    The 1st repe cmpsb processes

    ES:DI = foeg
    DS:SI = grim
    

    The 2nd repe cmpsb processes

    ES:DI = oegr
    DS:SI = grim
    

    The 3rd repe cmpsb processes

    ES:DI = egri
    DS:SI = grim
    

    The 4th repe cmpsb processes

    ES:DI = grim
    DS:SI = grim
    

    And bingo!