Home > Blockchain >  Remove first occurring space from string in assembly 8086
Remove first occurring space from string in assembly 8086

Time:04-05

The problem is to remove first occurring space from string in assembly 8086. I have written a test code, which apparently is not working. My idea is the following: set both di and si to be equal to the same string. keep di the same as long as no character is found. as soon as a character is found start setting di to the values that come afterwards. In this case "sometext mytext" should stay the same after 8 iterations and then "sometext mytext" -> "sometextmmytext" -> "sometextmyytext" -> ... -> "sometextmytexxt" -> "sometextmytext$$"

then last $ can be removed by hand.

Now, I am using the flag CF to know if the space has been found or not. But strangely, CF becomes set sooner than it should and when I try to debug the code I see that di is changing when it still shouldn't. Am I debugging wrongly or is something really wrong regarding my code that depends on CF? Also, if I run the code that I have posted it will say "not found" which is also weird. This makes me thing that the logic of my code is completely flawed yet I don't understand why. Could you explain me what is wrong and maybe post or hint to a better solution? I have also tried to solve using lods/stos but I failed that too. Thanks in advance.

P.S. as you can guess I'm new to assembly. maybe in some places my code is uselessly long when I could keep it shorter (I didn't focus on this task that much as I'm still trying to get this code to work). Also I might be righting inefficient code (even though my priority now is solving the problem itself). But, any advise is welcome.

EDIT: I have hardcoded the length of the string, I know that it can be retrieved from its first byte, but I was trying to solve for this sample at first.

.model small
.stack 256

.data
a db "sometext mytext$"
b db 10,"found$"
c db 10,"not found$"
.code

entrr proc
    push ax dx
    mov ah,2
    mov dl,10
    int 21h
    mov dl,13
    int 21h
    pop dx ax
    ret
entrr endp

PRINT MACRO x
    push ax
    push dx
    mov ah,09
    mov dx,x
    int 21h
    pop dx
    pop ax
ENDM

START:
    mov ax,@data
    mov ds,ax

    mov bl, ' '
    mov cl, '$'
    xor ax,ax
    xor cx,cx

    clc
    lea si, a
    lea di, a
compare:
    cmp cx, 15
    je endstr

    jnc check_for_space
    jc setdi

    inc cx
    jmp compare 
check_for_space:
    cmp [si 1], bl
    je found
    inc di
    inc si
    inc cx
    jmp compare
setdi:
    mov bl,[si 1]
    mov [di],bl
    inc di
    inc cx
    jmp compare
found:
    push di
    lea di,b
    PRINT di
    pop di

    stc
    inc si
    inc cx
    jmp compare
endstr:
    jnc notfound
    jmp done
notfound:
    lea si,c
    PRINT si
    jmp finish
done:
    ; print di
finish:
    mov ax,4c00h
    int 21h
END START

CodePudding user response:

compare:
    cmp cx, 15
    je endstr

    jnc check_for_space
    jc setdi

The culpritt is that cmp cx, 15 instruction at the top of the loop. cmp modifies the flags:

  • When CX is from 0 to 14, the code will obviously not jump to endstr, but because the carry flag will be set (the value in the register is below 15), the code will jump to setdi (something you don't want).
  • When CX finally becomes 15, the code will indeed jump to endstr, but because equality also entails that the carry flag will be clear, the code at endstr will jump to notfound

Next code should give you an idea:

  mov bl, ' '
  lea si, a       ; Address of the string
  mov di, si
  mov cx, 15      ; Length of the string
Again:
  cmp [si], bl
  je  IsSpace
  inc di
  inc si
  dec cx
  jnz Again
NotFound:
  ...
  jmp Quit

Copy:
  mov al, [si]
  mov [di], al
  inc di
IsSpace:
  inc si
  dec cx
  jnz Copy
Found:
  ...
Quit:
  ...

We don't jump to the top of the Copy loop because it could be that the space character was found at the last position in the string, fact that we recognize by the dec cx turning zero.

  • Related