Home > database >  Substring in a string display
Substring in a string display

Time:01-20

I am a begginer in assembly and I am trying to make a program where I should input 2 strings from the keyboard. The first string should be the main string and the second input is the substring which I need to look for in the main string. If I find it, I should display that it was found, and if not, I display that it wasn't found.

I tried to firstly compare the lenghts of the strings so if the first one has less chars than second, the message "Invalid" should be displayed. Then I tried to compare the substring with the string until the substring is found in the string and the message : "string found" is displayed, if not, the message : "string not found is displayed" . No matter what words I input, it will always say invalid. How can I change that? Here is my 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
     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


end start

CodePudding user response:

This should work: .model small

.stack 100h

print macro p

lea dx,p

mov ah,09h

int 21h

endm

.data

cn db 0

pn db 0

space db 10,13, " $"

msg db 10,13, "hjut$"

msg1 db "Introduceti primul sir:$"

msg2 db "Introduceti al doilea sir:$"

msg3 db "Al doilea sir nu se gaseste in primul.$"

msg4 db "Al doilea sir se gaseste in primul. $"

ar db 20 dup("$")

br db 20 dup("$")

.code

start:

mov ax,@data

mov ds,ax

mov si,01h

mov di,00h

mov cn,00h

print msg1

read1:mov ah,01h

int 21h

mov ar[si],al

inc si

cmp al,0dh

jnz read1

mov si,00h

print msg2

read2:mov ah,01h

int 21h

mov br[si],al

inc si

cmp al,0dh

jnz read2

mov si,00h

mov di,00h

jmp lop1

lop1: mov di,00h

inc si

mov bh,ar[si]

cmp bh,0dh

jz disp

mov bh,br[di]

cmp ar[si],bh

jnz lop1

jz lop2

lop2:inc si

inc di

mov bh,br[di]

cmp bh,0dh

jz l1

mov bh,br[di]

cmp ar[si],bh

jz lop2

jmp lop1

l1: add cn,01h

dec si

jmp lop1

disp:

cmp cn,00h

jz disp1

print msg4

add cn,30h

mov dl,cn

mov ah,02h

int 21h

jmp exit

disp1:print msg3

exit:mov ah,4ch

int 21h

end start

CodePudding user response:

I see that you have tried to apply some of the advice I gave in the answer at Finding the substring in an input string.
But it's gone wrong mostly because you decided to special-case where the inputted string has the same length as the inputted word. That's not a special case at all! If it so happens, my calculation of the number of possible finds will remain valid and yield a 1 in the BP register. In short, your problems originate from having inserted that valid part and not having edited the program accordingly.

add si, 2
add di, 2
je valid
jb matching
valid:
cld
repe cmpsb
je found_display
jne notfound_display

You don't need all of the above once you drop the redundant valid part.

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

And don't forget to remove any code that you don't actually need in your program, especially when you use code that you found on the internet.

Solution

  ...

  ; To check if the length of substring is shorter than the main string
  mov  cl, [si 1]
  mov  ch, 0
  mov  bl, [di 1]
  mov  bh, 0
  mov  bp, cx      ; CX is length string (long)
  sub  bp, bx      ; BX is length word  (short)
  jb   notfound_display
  inc  bp          ; -> BP is number of possible finds 1 
  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

  ...

Some optimization

  • I have absorbed the instructions cmp bx, cx ja invalid_length in the calculation of the number of possible finds (shaving off 2 bytes). If the subtraction produces a borrow, you know the word is longer than the string and so you can branch away. Whether you jump to invalid_length or notfound_display is up to you...

  • You can shorten this program by 2 bytes if you replace lea si, [InputString 2] lea di, [InputWord 2] by add si, 2 add di, 2.

  • Related