从程序集 8086 中的字符串中删除第一个出现的 space

Remove first occurring space from string in assembly 8086

问题是从程序集 8086 中的字符串中删除第一次出现的 space。 我写了一个测试代码,显然是行不通的。 我的想法如下:将 di 和 si 设置为等于同一个字符串。只要没有找到字符,就保持 di 不变。一旦找到一个字符,就开始将 di 设置为随后出现的值。在这种情况下,“sometext mytext”应该在 8 次迭代后保持不变,然后是“sometext mytext”->“sometextmmytext”->“sometextmyytext”-> ...->“sometextmytexxt”->“sometextmytext$$”

然后可以手动删除最后一个 $。

现在,我正在使用标志 CF 来了解是否找到了 space。但奇怪的是,CF 设置得比它应该设置的早,当我尝试调试代码时,我看到 di 在它仍然不应该改变的时候正在改变。我是在错误地调试还是我的依赖于 CF 的代码确实有问题?另外,如果我 运行 编辑了我 post 的代码,它会说“未找到”,这也很奇怪。这让我觉得我的代码逻辑完全有缺陷,但我不明白为什么。你能解释一下哪里出了问题,也许 post 或暗示更好的解决方案吗? 我也尝试使用 lods/stos 来解决,但我也失败了。提前致谢。

P.S。你可以猜到我是装配新手。也许在某些地方,当我可以保持代码更短时,我的代码变得毫无用处(我没有那么专注于此任务,因为我仍在尝试使此代码正常工作)。此外,我可能正在纠正低效代码(尽管我现在的首要任务是解决问题本身)。但是,欢迎任何建议。

编辑:我已经对字符串的长度进行了硬编码,我知道它可以从它的第一个字节中检索出来,但我一开始试图解决这个示例。

.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
compare:
    cmp cx, 15
    je endstr

    jnc check_for_space
    jc setdi

罪魁祸首是循环顶部的 cmp cx, 15 指令。 cmp 修改标志:

  • CX从0到14时,代码显然不会跳转到endstr,而是因为会设置进位标志(寄存器中的值低于 15),代码会跳转到setdi(你不想要的东西)。
  • CX最终变为15时,代码确实会跳转到endstr,但是因为相等也意味着进位标志将被清除,所以代码在endstr 会跳转到 notfound

接下来的代码应该会给你一个想法:

  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:
  ...

我们没有跳到Copy循环的顶部,因为可能是在字符串的最后一个位置找到了space字符,事实上我们通过 dec cx 变为零来识别。