string - 查找输入字符串中的子字符串

标签 string assembly x86-16 strstr

我有一个汇编程序,我需要在我输入的主字符串中找到子字符串。我的问题是,即使我输入了两个完全不同的单词,它总是输出“找到的单词”。我不知道我的循环或条件的哪一部分是错误的。请帮我弄清楚。另外,请建议一些可用于检查子字符串的字符串指令,以便我可以缩短我的代码。我真的很困惑 cmpsb 的工作原理,我只是尝试使用它。顺便说一句,我不知道如何使用调试器,这就是为什么我无法调试我的代码,而且我只是汇编语言的新手。

下面是我的代码的逻辑部分。

.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

最佳答案

strlen dw ($-InputWord)

这没有任何用处。它计算的长度对您没有任何帮助!

;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

这里(正如 Jester 告诉你的)add si, cx 指令是错误的。您需要 add si, 2SI 设置为字符串的开头。您还需要添加 add di, 2DI 设置为单词的开头。执行此操作,程序的有效部分将正常工作。


对于匹配部分:

考虑以下情况:字符串有 7 个字符,而您要查找的单词有 6 个字符。您最多可以通过两种方式找到该单词。

考虑字符串有 8 个字符而您要查找的单词有 6 个字符的情况。您最多可以通过 3 种方式找到该单词。

考虑以下情况:字符串有 9 个字符,而您要查找的单词有 6 个字符。您最多可以通过 4 种方式找到该单词。

注意到规律了吗?可能找到的数量等于长度差加 1。

    mov     bp, cx      ;CX is length string (long)
    sub     bp, bx      ;BX is length word  (short)
    inc     bp

这会将 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

检查部分将使用repe cmpsb来测试匹配,但如果未找到匹配,您必须能够返回到<继续标签处的em>匹配代码。您必须保留寄存器。

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

关于string - 查找输入字符串中的子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47513958/

相关文章:

java - 在 Java 中连接字符串是否总是会导致在内存中创建新字符串?

c++ - 如何将字符串转换为 float 数组?

gcc - 臂组件: '#define' risk

c++ - 如何在 x86 程序集中将当前线程的堆栈指针更改为新线程

assembly - 我可以将 al 插入 TASM 中的堆栈吗?

c - 汇编循环遍历字符串来计算字符数

c - 使用 SIGILL 与 CPU 探测的 AVX 特征检测

assembly - 如何在汇编中从用户输入多位数?

assembly - 是否有其他类似于 MOVZX 但在 8086 上支持的指令?

java - 调用 Scanner 的 nextLine 的方法上的输入不匹配异常