从程序集 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
变为零来识别。
问题是从程序集 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
变为零来识别。