Search code examples
stringassemblyx86-16tasmdosbox

Assembly word is substring of a string problem


I need to make this code which displays if a word is a substring of another. Both are read from the keyboard, firstly the string and then the word which I need to check if it's a substring.

The problem is that I input them and the output is:

Invalid. Word found. Word not found.

I tried to check if the second input is bigger than the first, so basically, it would compare them and display the message: "invalid." No matter what I write the output is the same: "Invalid. Word found. Word not found."

Here is my full code:

.model small
.stack 200h
.data
     prompt1 db "Input String: $"
     prompt2 db 10,10, 13, "Input Word: $"
     prompt3 db 10,10, 13, "Output: $"
     found db "Word Found. $"
     notfound db "Word Not Found. $"
     invalid db 10,10, 13, "Invalid. $"
     InputString db 21,?,21 dup("$")  
     InputWord db 21,?,21 dup("$")
     actlen db ?

.code
start:
      mov ax, @data
      mov ds, ax
      mov es, ax

     ;Getting input string
     mov ah,09h
     lea dx, prompt1
     int 21h

     lea si, InputString
     mov ah, 0Ah
     mov dx, si
     int 21h

     ;Getting input word
     mov ah,09h
     lea dx, prompt2
     int 21h

     lea di, InputWord
     mov ah, 0Ah
     mov dx, di
     int 21h

     ;To check if the length of substring is shorter than the main string
     mov cl, [si+1]
     mov ch, 0
     add si, 2
     add di, 2
     mov bl, [di+1]
     mov bh, 0
     cmp bx, cx
     ja invalid_length
     je valid
     jb matching

valid:
     cld
     repe cmpsb
     je found_display
     jne notfound_display
mov     bp, cx      ;CX is length string (long)
sub     bp, bx      ;BX is length word  (short)
inc     bp

cld
    lea     si, [InputString + 2]
    lea     di, [InputWord + 2]
matching:
    mov     al, [si]    ;Next character from the string
    cmp     al, [di]    ;Always the first character from the word
    je      check
continue:  
    inc     si          ;DI remains at start of the word
    dec     bp
    jnz     matching    ;More tries to do
    jmp     notfound_display

check:
    push    si
    push    di
    mov     cx, bx     ;BX is length of word
    repe cmpsb
    pop     di
    pop     si
    jne     continue
    jmp     found_display

again:
     mov si, ax    
     dec dx
     lea di, InputWord
     jmp matching


invalid_length:
     mov ah, 09h
     lea dx, invalid
     int 21h



found_display:
mov dx, offset found
mov ah, 09h
int 21h



notfound_display:
mov dx, offset notfound
mov ah, 09h
int 21h



end start

Solution

  • To clarify what Jester has already stated:

    invalid_length:
         mov ah, 09h
         lea dx, invalid
         int 21h
    
    found_display:
         mov dx, offset found
         mov ah, 09h
         int 21h
    
    notfound_display:
         mov dx, offset notfound
         mov ah, 09h
         int 21h
    
    end start
    

    Labels by themselves do not affect the operation of the ip register. This is because labels don't exist at runtime; they're merely a convenience for the programmer. So what your computer is actually doing with the above code is this:

    invalid_length:
         mov ah, 09h
         lea dx, invalid
         int 21h
         mov dx, offset found
         mov ah, 09h
         int 21h
         mov dx, offset notfound
         mov ah, 09h
         int 21h
    
    end start
    

    If you want only one of these three to be run, you need to redirect ip at the end of each. There are a few ways to do this, here's one:

    invalid_length:
         mov ah, 09h
         lea dx, invalid
         int 21h
         jmp done
    
    found_display:
         mov dx, offset found
         mov ah, 09h
         int 21h
         jmp done
    
    notfound_display:
         mov dx, offset notfound
         mov ah, 09h
         int 21h
         ;fallthrough is intentional
    
    done:
         mov ax,4C00h
         int 21h        ;exit program and return to DOS