子串搜索程序总是导致错误

时间:2013-09-09 16:29:32

标签: string assembly x86 masm x86-16

This gist托管所有必需的文件。我先解释一下我在这里做的事情。

目的

程序应该读取两个不同长度的单独字符串,小于200,由换行符终止。读取字符串后,搜索两个字符串中的任何一个是否是另一个字符串的子字符串。如果它们都是相同的;返回true。

返回值

  • TRUE :其中一个字符串是子字符串。
  • FALSE :两个字符串完全不同。

程序

我在我的计划中所做的是:

  1. 通过调用过程READ_STR将字符串读入变量STR1STR2。该过程返回BX中的字符串长度。我将第一个字符串的长度存储在L1类型的另一个变量DW中。
  2. 将第二个字符串(现在位于BX)的长度与L1进行比较。

    • 如果两者相等,请将CX设为1
    • 其他设置CX = abs.( BX - L1 ) |绝对BX - L1

    这是设置较小字符串在较大字符串内迭代的次数。将DI设置为指向较长的字符串。

  3. L1设置为较小字符串的长度。
  4. DX设为0.开始一个值为CX的循环,如上所述。
  5. DX添加到DI并使用CMPSB将较短的字符串SI与较长的字符DI进行比较。将CX更新为L1,以便REPE CMPSB可以正常运行。
  6. 如果搜索失败,则增加DX。重置CXDISI。将CX递减1后(从LOOP操作完成),从步骤4开始。
  7. 一些输出

    out

    由于following statements(第72行和第73行),第三个输出中有一个额外的行。对DISP_STR的调用失败。

    NEWLINE
    CALL DISP_STR
    

    代码

    PROG.ASM

    TITLE Assignment: Read two strings and ...
    
    .MODEL SMALL
    
        SAVE_REG MACRO REGS
            IRP D, <REGS>
                PUSH D
            ENDM
        ENDM
        LOAD_REG MACRO REGS
            IRP D, <REGS>
                POP D
            ENDM
        ENDM
        END_DOS MACRO
            MOV AH, 76
            INT 21H
        ENDM
        NEWLINE MACRO
            SAVE_REG <AX, DX>
            MOV AH, 2
            MOV DL, 0AH
            INT 21H
            MOV DL, 0DH
            INT 21H
            LOAD_REG <DX, AX>
        ENDM
    
    .STACK 100H
    
    .DATA
    
        STR1 DB 200 DUP(65)
        STR2 DB 200 DUP(0)
        PROMPT DB "Enter string "
        NUM DB "1: $"
        L1 DW 0
        UNEQL DB "No substring found$"
        EQUAL DB "Substring was found$"
    .CODE
    
    MAIN PROC
    
        MOV AX, @DATA
        MOV DS, AX
        MOV ES, AX
        MOV AH, 9
        LEA DX, PROMPT
        INT 21H
        LEA DI, STR1
        CALL READ_STR
        MOV L1, BX
        NEWLINE
        MOV NUM, '2'
        INT 21H
        CALL READ_STR
        LEA SI, STR1
        LEA DI, STR2        ; DI stores the longer string
        CMP L1, BX
          JE EQL
        CMP L1, BX
          JG INV
        MOV CX, BX
        SUB CX, L1
        JMP COMPARE
        INV:
        MOV CX, L1
        SUB CX, BX
        MOV L1, BX
        LEA SI, STR2
        LEA DI, STR1        ; DI stores longer string
        NEWLINE
        CALL DISP_STR
        JMP COMPARE
        EQL:
        MOV CX, 1
        COMPARE:
        XOR DX, DX
        TOP:
        SAVE_REG <DI, SI>
        ADD DI, DX
        PUSH CX
        MOV CX, L1
        REPE CMPSB
          JCXZ FOUND
        INC DX
        POP CX
        LOAD_REG <SI, DI>
        LOOP TOP
        NOT_FOUND:
        NEWLINE
        LEA DX, UNEQL
        MOV AH, 9
        INT 21H
        END_DOS
        FOUND:
        POP CX
        LOAD_REG <SI, DI>
        NEWLINE
        LEA DX, EQUAL
        MOV AH, 9
        INT 21H
        END_DOS
    
    MAIN ENDP
    
        INCLUDE READSTR.ASM
        INCLUDE DISPSTR.ASM
    
    END MAIN
    

    DISPSTR.ASM

    DISP_STR PROC
    
        SAVE_REG <AX, CX, DX, SI>
        MOV CX, BX
        CLD
        MOV AH, 2
        DISP_LOOP:
        LODSB
        MOV DL, AL
        INT 21H
        LOOP DISP_LOOP
        LOAD_REG <SI, DX, CX, AX>
        RET
    
    DISP_STR ENDP
    

    READSTR.ASM

    READ_STR PROC
    
        SAVE_REG <AX, DI>
        XOR BX, BX
        CLD
        MOV AH, 1
        INT 21H
        WHILE_LOOP:
        CMP AL, 0DH
          JE END_WHILE
        CMP AL, 08H
          JNE STORAGE
        DEC BX
        DEC DI
        JMP NEXT
        STORAGE:
        STOSB
        INC BX
        NEXT:
        INT 21H
        JMP WHILE_LOOP
        END_WHILE:
        LOAD_REG <DI, AX>
        RET
    
    READ_STR ENDP
    

2 个答案:

答案 0 :(得分:2)

您应该学会使用调试器,以便自己修复代码。

无论如何,从快速浏览一下,第一个明显的问题是,当您使用READ_STR来阅读第二个字符串时,您没有将DI设置为指向STR2。因此,由于READ_STR保留DI,第二个字符串也将被读入STR1,覆盖第一个字符串。解决方案:将line 58上的LEA DI, STR2移至line 56之前。如果没有潜伏的其他错误,那应该解决它。

答案 1 :(得分:0)

在我看来,你可以使用这个程序:

您应该使用最短的字符串并尝试将其第一个字母与最长字符串中的所有字母进行比较,一旦比较结果为真,请转到最短字符串中的下一个字母并尝试将其与下一个字母进行比较。最长的字符串。

前段时间,我在MASM32中编写了一个单词unscrambler。用户在程序字典中提供一个乱码字,程序解读它并显示正确的单词。

在它的工作方式中,在处理每个字母时,对你来说可能会有点帮助。

这是我制作的解码器的代码:

.386
.model flat, stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/masm32.inc
include /masm32/include/kernel32.inc

includelib /masm32/lib/masm32.lib
includelib /masm32/lib/kernel32.lib

.data
not_found db "not_found",0
word0   db  "souhail",0
word1   db  "ability",0
word2  db"absence",0
word3 db "actions",0
word4  db "amazing",0 
word5  db "believe", 0
word6  db "browser", 0
word7  db "caption", 0
word8  db "captive", 0
word9  db "ceiling", 0
word10  db "degrees", 0
word11  db "denizen", 0
word12  db "develop", 0
word13  db "examine", 0
word14  db "example", 0
word15  db "exploit", 0
word16  db "fifteen", 0
word17  db "focused", 0
word18  db "fortune", 0
word19  db "forward",0
word20  db  "garbage", 0
word21  db  "gasping", 0
word22  db  "graphic", 0
word23  db  "handgun", 0
word24  db  "hastily", 0
word25  db  "helpful",0 
word26  db  "iceberg", 0
word27 db    "impeach", 0
word28 db    "inspect",0
word29 db    "jawbone", 0
word30 db     "justify", 0
word31 db     "keyword", 0
word32 db     "kickoff", 0
word33 db     "kneepad", 0
word34 db     "lactose", 0
word35 db     "latency", 0
word36 db     "legible", 0
word37 db     "madness", 0
word38 db     "magical", 0
word39 db     "manhunt", 0
word40 db     "mission", 0
word41 db     "nametag", 0
word42 db    "nitrate", 0
word43 db     "nowhere", 0
word44 db     "officer", 0
word45 db     "optical", 0
word46 db     "outlook", 0
word47 db     "oxidize", 0
word48 db     "paradox", 0
word49 db     "pathway", 0
word50 db     "patient", 0
word51 db     "payment", 0
word52 db     "qualify", 0
word53 db     "quality", 0
word54 db     "quarrel", 0
word55 db     "radical", 0
word56 db     "railing", 0
word57 db     "reduced", 0
word59 db     "resolve", 0
word60 db     "savings", 0
word61 db     "sayings", 0
word62 db     "scissor", 0
word63 db     "shadows", 0
word64 db     "tactics", 0
word65 db     "teacher", 0
word66 db     "terrify", 0
word67 db     "tractor", 0
word68 db     "unarmed", 0
word69 db     "unmasks", 0
word70 db     "updates", 0
word71 db     "vaccine", 0
word72 db     "valleys", 0
word73 db     "walnuts", 0
word74 db     "wealthy", 0
word75 db     "whacked", 0
word76 db     "willing", 0
word77 db     "wizards", 0
word78 db     "xysters", 0
word79 db     "yielded", 0
word80 db     "yoghurt", 0
word81 db     "younger",0
word82 db     "zippers" ,0
word83 db     "zombies",0
.data?
my_words db 1024 dup(?)
printme db  1024     dup(?)
exit        db  1024    dup(?)


.code
start :
First :
invoke StdIn, addr my_words, 200
lea eax, my_words
mov word ptr [eax+7],00
mov word ptr [eax+10h],00
lea edx, word1
push edx
mov esi,7                   ;set target word counter 
mov bl,byte ptr [eax]       ; mov first letter of input to bl

compare :
mov cl, byte ptr [edx]      ;mov letter of targer word to cl
cmp bl,cl
je add_one_to_my_word
inc edx
dec esi
cmp esi,0
je switch_to_next
jmp compare

add_one_to_my_word :
inc eax
mov bl,byte ptr [eax]
mov edx, dword ptr [esp] 
mov esi,7
cmp bl,0
je store1
jmp compare

switch_to_next :
lea eax,my_words
mov bl, byte ptr [eax]
pop edx
add edx,8
push edx
mov esi,7
cmp byte ptr [edx], 0
je notfound
jmp compare

store1 :
pop edx
lea eax, printme

store_12 :
mov bl, byte ptr [edx]
mov byte ptr [eax], bl
inc eax
inc edx
cmp byte ptr [edx], 0
jnz store_12

;invoke StdOut, addr printme
;invoke StdIn, addr exit, 200

Second :
lea eax, my_words
add eax,9
lea edx, word1
push edx
mov esi,7                   ;set target word counter 
mov bl,byte ptr [eax]       ; mov first letter of input to bl

compare2 :
mov cl, byte ptr [edx]      ;mov letter of targer word to cl
cmp bl,cl
je add_one_to_my_word_2
inc edx
dec esi
cmp esi,0
je switch_to_next_2
jmp compare2

add_one_to_my_word_2 :
inc eax
mov bl,byte ptr [eax]
mov edx, dword ptr [esp] 
mov esi,7
cmp bl,0
je store2
jmp compare2

switch_to_next_2 :
lea eax,my_words
add eax,9
mov bl, byte ptr [eax]
pop edx
add edx,8
push edx
mov esi,7
cmp byte ptr [edx], 0
je notfound
jmp compare2

store2 :
pop edx
lea eax, printme
add eax,8

store_22 :
mov bl, byte ptr [edx]
mov byte ptr [eax], bl
inc eax
inc edx
cmp byte ptr [edx], 0
jnz store_22

Third :
lea eax, my_words
add eax,12h
lea edx, word1
push edx
mov esi,7           ;set target word counter 
mov bl,byte ptr [eax]       ; mov first letter of input to bl

compare3 :
mov cl, byte ptr [edx]      ;mov letter of targer word to cl
cmp bl,cl
je add_one_to_my_word_3
inc edx
dec esi
cmp esi,0
je switch_to_next_3
jmp compare3

add_one_to_my_word_3 :
inc eax
mov bl,byte ptr [eax]
mov edx, dword ptr [esp] 
mov esi,7
cmp bl,0
je store3
jmp compare3

switch_to_next_3 :
lea eax,my_words
add eax,12h
mov bl, byte ptr [eax]
pop edx
add edx,8
push edx
mov esi,7
cmp byte ptr [edx], 0
je notfound
jmp compare3

store3 :
pop edx
lea eax, printme
add eax,11h

store_23 :
mov bl, byte ptr [edx]
mov byte ptr [eax], bl
inc eax
inc edx
cmp byte ptr [edx], 0
jnz store_23

Put_Order :
lea eax, printme
add eax,7
mov byte ptr [eax], 2Ch
add eax,8
mov word ptr [eax],202Ch
invoke StdOut, addr printme
invoke StdIn, addr exit, 200
call start
notfound :
invoke StdOut, addr not_found
invoke StdIn , addr exit,200


end start