问题
I have this assembly program where I need to find the substring in the main string I input. My problem is that it always outputs the "word found" even if I typed two completely different words. I don't know which part of my loop or condition is wrong. Please help me figure it out. Also, please suggest some string instructions that could be used in checking for a substring so that I can shorten my code. I am really confused with how the cmpsb
works, I only tried to use it. Btw, I don't know how to use a debugger that's why I can't debug my code and I am just a newbie in assembly language.
Below is the logic part of my code.
.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 ?
strlen dw ($-InputWord)
.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, cx
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
matching:
mov al, [si]
mov ah, [di]
cmp al, ah
je check
jne iterate
iterate:
inc si
mov dx, strlen
dec dx
cmp dx, 0
je notfound_display
jmp matching
check:
mov cl, [di+1]
mov ch, 0
mov ax, si
add ax, 1
cld
repe cmpsb
jne again
jmp found_display
again:
mov si, ax
dec dx
lea di, InputWord
jmp matching
invalid_length:
mov ah, 09h
lea dx, invalid
int 21h
回答1:
strlen dw ($-InputWord)
This does nothing useful. The length that it calculate can not help you in any way!
;To check if the length of substring is shorter than the main string mov cl, [si+1] mov ch, 0 add si, cx mov bl, [di+1] mov bh, 0 cmp bx, cx
Here (as Jester told you) the add si, cx
instruction is wrong. You need add si, 2
to set SI
to the start of the string. You will also need to add add di, 2
to set DI
to the start of the word. Do this and the valid part of your program will work correctly.
For the matching part:
Consider the case where the string has 7 characters and the word that you're looking for has 6 characters. You can find the word in at most 2 ways.
Consider the case where the string has 8 characters and the word that you're looking for has 6 characters. You can find the word in at most 3 ways.
Consider the case where the string has 9 characters and the word that you're looking for has 6 characters. You can find the word in at most 4 ways.
Notice the regularity? The number of possible finds is equal to the difference in length plus 1.
mov bp, cx ;CX is length string (long)
sub bp, bx ;BX is length word (short)
inc bp
This sets BP
to the number of tries in your matching routine.
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
The check part will use repe cmpsb
to test for a match, but in the event that the match is not found, you must be able to return to the matching code at the continue label. You have to preserve the registers.
check:
push si
push di
mov cx, bx ;BX is length of word
repe cmpsb
pop di
pop si
jne continue
jmp found_display
来源:https://stackoverflow.com/questions/47513958/finding-the-substring-in-an-input-string