Snow Max
Snow Max

Reputation: 9

Assembler delete word

I need help with assembler(TASM), and I need to change one problem.

When filling a buffer of 200 elements, I need to make a transition to entering a word for deletion, but it does not work, help

.MODEL small
.STACK 100h

.DATA
msg1 DB "Enter string: $"
msg2 DB 0Ah, 0Dh, "Enter word to delete: $"
msg3 DB 0Ah, 0Dh, "Result: $"

str1ml DB 200          ; maximum buffer length
str1l  DB 0            ; actual length of the entered string (DOS format)
str1   DB 200 dup('$') ; the characters of the string, filled with '$'

str2ml DB 200
str2l  DB 0
str2   DB 200 dup('$')

.CODE
begin:
    ; Initialize DS and ES segments
    mov ax, @data
    mov ds, ax
    mov es, ax
    xor ax, ax

    ; Print message and input the main string
    lea dx, msg1
    call strout
    lea dx, str1ml
    call strin

    ; Check if the buffer is full
    mov al, str1l
    cmp al, str1ml
    jb input_word      ; if the buffer is not full, proceed to input the word
    ; If the buffer is full, add a terminating character
    mov byte ptr [str1 + 200], '$' ; add a terminating character

input_word:
    ; Print message and input the substring (word to delete)
    lea dx, msg2
    call strout
    lea dx, str2ml
    call strin

    ; Check if the buffer is full
    mov al, str2l
    cmp al, str2ml
    jb process_input   ; if the buffer is not full, proceed to processing
    ; If the buffer is full, add a terminating character
    mov byte ptr [str2 + 199], '$' ; add a terminating character

process_input:
    ; Prepare to search for the substring in the main string
    xor cx, cx
    mov cl, str1l      ; load the length of the main string
    sub cl, str2l      ; calculate the number of possible positions for comparison
    inc cl            ; account for the last possible shift
    cld               ; clear the direction flag (forward traversal)
    lea di, str2      ; DI points to the beginning of the substring
    lea si, str1      ; SI points to the beginning of the main string
    xor ax, ax

all_string:
    ; Search for a match of the substring at the current position in the main string
    call sub_search
    inc si            ; shift one character to the right in the main string
    loop all_string   ; repeat the loop until CX is zero

    ; Move to a new line
    call nextstr

    ; Print the final result
    lea dx, msg3
    call strout
    lea dx, str1
    call strout

_end:
    mov ah, 4Ch      ; DOS function to terminate the program
    int 21h

; Procedure to move to a new line
nextstr proc
    push dx
    push ax
    mov dl, 0Dh      ; carriage return character
    mov ah, 02h
    int 21h
    mov dl, 0Ah      ; line feed character
    mov ah, 02h
    int 21h
    pop ax
    pop dx
    ret
nextstr endp

; Procedure to input a string (DOS function 0Ah)
strin proc
    mov ah, 0Ah
    int 21h
    ret
strin endp

; Procedure to output a string (DOS function 09h)
strout proc
    mov ah, 09h
    int 21h
    ret
strout endp

; Procedure to search for a substring in a string
sub_search proc
    push cx
    push di
    push si
    mov bx, si      ; save the starting address of the current comparison
    mov cl, str2l   ; set the counter to the length of the substring
    repe cmpsb      ; compare bytes while they are equal (SI and DI)
    je _eq          ; if all characters are equal, jump to deletion
    jne _neq        ; if a mismatch is found, jump to the end
_eq:
    call delete     ; call the procedure to delete the substring
    inc al
_neq:
    pop si
    pop di
    pop cx
    ret
sub_search endp

; Procedure to delete a substring
delete proc
    push bx
    push di
    push si
    mov di, bx      ; DI points to the beginning of the substring to delete
    lea si, [bx + str2l] ; SI points to the character after the substring
    mov cx, 200     ; maximum length of the string
    sub cx, bx      ; calculate the remaining length of the string
    rep movsb       ; copy the remaining part of the string
    pop si
    pop di
    pop bx
    ret
delete endp

end begin

What I Tried: I translated the comments in your assembly code from Russian to English to make it easier for English-speaking developers to understand the logic and purpose of each section of the code. I expected this to help clarify the functionality of the program, especially for those who might not be familiar with Russian.

Upvotes: 0

Views: 45

Answers (1)

Sep Roland
Sep Roland

Reputation: 39506

Your program is not all that bad! Where it goes terribly wrong is in the delete proc. You move too many bytes down, you forget to $-terminate the resulting string, and you need to update the length variable for the first string so your all_string loop could successfully repeat the operation in case the substring appears multiple times.

lea si, [bx + str2l] ; SI points to the character after the substring

Since delete is reached from within sub_search, the successful repe cmpsb will already have left the SI register pointing to the character after the substring. So this is a redundant instruction, as well as it is wrong in that you mistakenly use the address of str2l instead of the actual length!

mov cx, 200     ; maximum length of the string
sub cx, bx      ; calculate the remaining length of the string

You can't subtract an address (BX) from a length (200) just like that!
You can obtain the number of bytes to copy, from subtracting the address where the block starts (SI) from the address where the block ends (str1 + [str1l]).

What follows is an improved delete procedure, but you should not yet try to continue your all_string loop from it, because that would require additional improvements. At a minimum you should respond to this answer first ...

; IN (bx,si) OUT ()
  push ax
  push cx
  push si
  push di
  mov  di, bx    ; Points to the beginning of substring to delete
  mov  cx, OFFSET str1
  add  cl, str1l ; CURRENT length of the string
  adc  ch, 0
  sub  cx, si    ; -> CX is the length of remaining string
  rep movsb      ; copy the remaining part of the string
  mov  byte ptr [di], "$"
  mov  al, str2l
  sub  str1l, al ; New current length of the string
  pop  di
  pop  si
  pop  cx
  pop  ax
  ret

Upvotes: 1

Related Questions