Search code examples
stringassemblyx86masmx86-16

Substring search program always results in false


This gist hosts all required files. I'll first explain what I'm doing here.

Objective

The program should read two separate strings of various lengths, less than 200, terminated by a newline character. After reading the strings, search if either of the two string is a sub-string of another. In case that both of them are the same; return true.

Return values

  • TRUE: One of the string IS a sub-string.
  • FALSE: Both strings are entirely different.

Procedure

What I'm doing in my program is:

  1. Read the strings into variables STR1 and STR2 by calling the procedure READ_STR. The procedure returns the length of strings in BX. I'm storing the length of first string in another variable L1 of type DW.
  2. Compare the length of second string (now in BX) with L1.

    • If both are equal, set CX to 1
    • Else set CX = abs.( BX - L1 ) | Absolute of BX - L1.

    This is to set how many times can a smaller string be iterated inside the larger one. Set the DI to point to the longer string.

  3. Set L1 to be the length of smaller string.
  4. Set DX as 0. Start a loop with the value of CX as set above.
  5. Add DX to DI and use CMPSB to compare the shorter string SI with longer one DI. Update CX to be L1 so that REPE CMPSB can work.
  6. Increment DX if the search failed. Reset CX, DI and SI. Start from step 4 after decrementing CX by 1 (done by using the LOOP operation).

Some outputs

out

There is an extra line in the third output because of the following statements (line #72 & #73). The call to DISP_STR failed.

NEWLINE
CALL DISP_STR

Code

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

Solution

  • You should learn to use a debugger so you can fix your code yourself.

    Anyway, from a quick glance, the first obvious problem is that when you use READ_STR to read the second string you don't set up DI to point at STR2. As such, since READ_STR preserves DI, the second string will be read into STR1 too, overwriting the first. Solution: move the LEA DI, STR2 on line 58 up to before line 56. If there are no other errors lurking, that should fix it.