查找字母按字母顺序排列的单词
find words where letters ordered by alphabet
我正在尝试使用汇编查找句子中字母按字母顺序排列的单词。
例如:
Hello my name is acxz i am frz asw
程序应该return:
acxz frz asw
我在emu8086上写过一些代码,但是一直循环下去,找不到错误。简而言之,我想拆分我的句子,遍历每个单词并找到主字母字符串中每个字母的偏移量,然后将其与下一个字母进行比较,以确定前一个字母是否在字母字符串中的下一个字母之前。我不是装配专业人士,所以我无法找出问题所在。我的错误在哪里?提前致谢!
sseg SEGMENT stack 'stack'
DB 256 DUP(?)
sseg ENDS
dseg SEGMENT 'data'
STR1 DB "ENTER YOUR STRING HERE ->$"
STR2 DB "YOUR STRING IS ->$"
STR3 DB "WORD IS ->$"
INSTR1 DB 250 DUP("$")
INWORD DB 50 DUP("$")
NEWLINE DB 10,13,"$"
LENGTH1 DW $-INSTR1
BEGINNING DW 10 DUP("$")
ENDING DW 0
SEPARATORS DB " "
ALPHABET DB "abcdefghijklmnopqrstuvwxz"
ALPH_LENGTH DW 26
INWORD_LEN DW 0
dseg ENDS
cseg SEGMENT 'code'
ASSUME cs:cseg,ss:sseg,ds:dseg,es:cseg
Main PROC FAR
PUSH DS
XOR AX,AX
PUSH AX
MOV AX,dseg
MOV DS,AX
MOV ES,AX
@beginning:
LEA SI,INSTR1 + 2
XOR AX,AX
LEA DX,STR1
MOV AH,09H
INT 21H
XOR AX,AX
MOV AH,0AH
LEA DX,INSTR1
INT 21H
XOR CX,CX
MOV CL,[INSTR1 + 1]
LEA DI,INSTR1 + 2
ADD DI,CX
XOR AX,AX
MOV AL,'$'
STOSB
LEA DI,INSTR1 + 2
@skip_separators:
;JCXZ @print_result
@separators_loop:
LODSB
PUSH CX
LEA DI,SEPARATORS
MOV CX,1
REPNE SCASB
POP CX
JNE @word_begin
LOOP @separators_loop
@word_begin:
DEC SI
MOV BEGINNING,SI
@skip_word:
LODSB
PUSH CX
LEA DI,SEPARATORS
MOV CX,1
REPNE SCASB
POP CX
JE @word_end
LOOP @skip_word
@word_end:
DEC SI
MOV ENDING,SI
DEC ENDING
;jmp @exit
@word_check:
MOV SI,ENDING
LEA DI,INWORD
MOV CX,3
CMP CX,1
JE @buffer_word
@buffer_word:
STD
LODSB
CLD
STOSB
LOOP @buffer_word
MOV CX,3
MOV SI,BEGINNING
LEA DI,INWORD
REPE CMPSB
JNE @set_pointers
@set_pointers:
POP CX
MOV SI,ENDING
INC SI
JMP @skip_separators
@checking:
;MOV AX, ENDING
;CMP INWORD, AX
;JGE word_found
;POP CX
;CMP CX, DI
;JNE do_check
;jMP skip
MOV CX, BX
LEA DI, ALPHABET
LEA SI, INWORD
@do_check:
LODSB
PUSH CX
MOV CX, ALPH_LENGTH
REPNE SCASB
POP CX
JNE @not_found
loop @do_check
@word_found:
; code if word found
@not_found:
XOR AX,AX
MOV AH,09H
LEA DX,NEWLINE
INT 21H
XOR AX,AX
MOV AH,09H
LEA DX,INSTR1
INT 21H
RET
Main ENDP
cseg ENDS
end Main
说什么?
"Hello my name is acxz i am frz asw"
Program should return:
"acxz frz asw"
根据您所说的程序应该执行的操作,输出应该是:
my is acxz i am frz asw
有限的错误列表
assume
相对于 ES
是错误的 - 你已经将它耦合到 cseg
而稍后你将正确地将它设置为 dseg
.
ASSUME cs:cseg,ss:sseg,ds:dseg,es:Dseg
如果您的 separators_loop 完成 (CX
=0),您需要以某种方式退出程序。
LOOP @separators_loop
jmp @exit
word_check 部分当前所做的是检查单词的前 3 个字符是否等于后 3 个字符的倒序同一个单词的字符。这不仅 不是 您想要实现的目标,您也只是忽略结果并继续 set_pointers 代码。
崩溃的问题
@set_pointers:
POP CX
MOV SI,ENDING
INC SI
JMP @skip_separators
堆栈上没有任何有用的东西可以弹出 CX
寄存器!
对于 1 或 2 个单词的输入句子,此 pop cx
将偶然发现 AX
和 DS
的初始推值,但对于更长的句子,将发生什么事情的可能性不大.
一个建议
停止使用字符串原始指令(尤其是 SCASB
),就好像你的生命依赖于它们一样。你在任何地方都使用了这些,你把事情复杂化了很多。
举个例子,这就是白色space跳绳应该做的:
@separators_loop:
lodsb
cmp al, " "
loope @separators_loop
jz @exit
@word_begin:
现在呢?
要使这项工作正常进行,您需要先简化任务。
- 获取用户的输入
- 从此输入中提取单个单词
- 在屏幕上回显这个词,后跟一个 space 字符
- 重复步骤 2 和 4 直到
CX
=0
然后为了完成原始任务,您在 2 和 4 之间插入了一个额外的步骤来验证单词。如果没有,则直接进行第5步
- 获取用户的输入
- 从此输入中提取单个单词
- 检查是否按字母顺序排列,如果不是则转到第 5 步
- 在屏幕上回显这个词,后跟一个 space 字符
- 重复步骤 2、3 和 4 直到
CX
=0
我正在尝试使用汇编查找句子中字母按字母顺序排列的单词。 例如:
Hello my name is acxz i am frz asw
程序应该return:
acxz frz asw
我在emu8086上写过一些代码,但是一直循环下去,找不到错误。简而言之,我想拆分我的句子,遍历每个单词并找到主字母字符串中每个字母的偏移量,然后将其与下一个字母进行比较,以确定前一个字母是否在字母字符串中的下一个字母之前。我不是装配专业人士,所以我无法找出问题所在。我的错误在哪里?提前致谢!
sseg SEGMENT stack 'stack'
DB 256 DUP(?)
sseg ENDS
dseg SEGMENT 'data'
STR1 DB "ENTER YOUR STRING HERE ->$"
STR2 DB "YOUR STRING IS ->$"
STR3 DB "WORD IS ->$"
INSTR1 DB 250 DUP("$")
INWORD DB 50 DUP("$")
NEWLINE DB 10,13,"$"
LENGTH1 DW $-INSTR1
BEGINNING DW 10 DUP("$")
ENDING DW 0
SEPARATORS DB " "
ALPHABET DB "abcdefghijklmnopqrstuvwxz"
ALPH_LENGTH DW 26
INWORD_LEN DW 0
dseg ENDS
cseg SEGMENT 'code'
ASSUME cs:cseg,ss:sseg,ds:dseg,es:cseg
Main PROC FAR
PUSH DS
XOR AX,AX
PUSH AX
MOV AX,dseg
MOV DS,AX
MOV ES,AX
@beginning:
LEA SI,INSTR1 + 2
XOR AX,AX
LEA DX,STR1
MOV AH,09H
INT 21H
XOR AX,AX
MOV AH,0AH
LEA DX,INSTR1
INT 21H
XOR CX,CX
MOV CL,[INSTR1 + 1]
LEA DI,INSTR1 + 2
ADD DI,CX
XOR AX,AX
MOV AL,'$'
STOSB
LEA DI,INSTR1 + 2
@skip_separators:
;JCXZ @print_result
@separators_loop:
LODSB
PUSH CX
LEA DI,SEPARATORS
MOV CX,1
REPNE SCASB
POP CX
JNE @word_begin
LOOP @separators_loop
@word_begin:
DEC SI
MOV BEGINNING,SI
@skip_word:
LODSB
PUSH CX
LEA DI,SEPARATORS
MOV CX,1
REPNE SCASB
POP CX
JE @word_end
LOOP @skip_word
@word_end:
DEC SI
MOV ENDING,SI
DEC ENDING
;jmp @exit
@word_check:
MOV SI,ENDING
LEA DI,INWORD
MOV CX,3
CMP CX,1
JE @buffer_word
@buffer_word:
STD
LODSB
CLD
STOSB
LOOP @buffer_word
MOV CX,3
MOV SI,BEGINNING
LEA DI,INWORD
REPE CMPSB
JNE @set_pointers
@set_pointers:
POP CX
MOV SI,ENDING
INC SI
JMP @skip_separators
@checking:
;MOV AX, ENDING
;CMP INWORD, AX
;JGE word_found
;POP CX
;CMP CX, DI
;JNE do_check
;jMP skip
MOV CX, BX
LEA DI, ALPHABET
LEA SI, INWORD
@do_check:
LODSB
PUSH CX
MOV CX, ALPH_LENGTH
REPNE SCASB
POP CX
JNE @not_found
loop @do_check
@word_found:
; code if word found
@not_found:
XOR AX,AX
MOV AH,09H
LEA DX,NEWLINE
INT 21H
XOR AX,AX
MOV AH,09H
LEA DX,INSTR1
INT 21H
RET
Main ENDP
cseg ENDS
end Main
说什么?
"Hello my name is acxz i am frz asw"
Program should return:
"acxz frz asw"
根据您所说的程序应该执行的操作,输出应该是:
my is acxz i am frz asw
有限的错误列表
assume
相对于ES
是错误的 - 你已经将它耦合到cseg
而稍后你将正确地将它设置为dseg
.ASSUME cs:cseg,ss:sseg,ds:dseg,es:Dseg
如果您的 separators_loop 完成 (
CX
=0),您需要以某种方式退出程序。LOOP @separators_loop jmp @exit
word_check 部分当前所做的是检查单词的前 3 个字符是否等于后 3 个字符的倒序同一个单词的字符。这不仅 不是 您想要实现的目标,您也只是忽略结果并继续 set_pointers 代码。
崩溃的问题
@set_pointers:
POP CX
MOV SI,ENDING
INC SI
JMP @skip_separators
堆栈上没有任何有用的东西可以弹出 CX
寄存器!
对于 1 或 2 个单词的输入句子,此 pop cx
将偶然发现 AX
和 DS
的初始推值,但对于更长的句子,将发生什么事情的可能性不大.
一个建议
停止使用字符串原始指令(尤其是 SCASB
),就好像你的生命依赖于它们一样。你在任何地方都使用了这些,你把事情复杂化了很多。
举个例子,这就是白色space跳绳应该做的:
@separators_loop:
lodsb
cmp al, " "
loope @separators_loop
jz @exit
@word_begin:
现在呢?
要使这项工作正常进行,您需要先简化任务。
- 获取用户的输入
- 从此输入中提取单个单词
- 在屏幕上回显这个词,后跟一个 space 字符
- 重复步骤 2 和 4 直到
CX
=0
然后为了完成原始任务,您在 2 和 4 之间插入了一个额外的步骤来验证单词。如果没有,则直接进行第5步
- 获取用户的输入
- 从此输入中提取单个单词
- 检查是否按字母顺序排列,如果不是则转到第 5 步
- 在屏幕上回显这个词,后跟一个 space 字符
- 重复步骤 2、3 和 4 直到
CX
=0