查找字母按字母顺序排列的单词

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 将偶然发现 AXDS 的初始推值,但对于更长的句子,将发生什么事情的可能性不大.


一个建议

停止使用字符串原始指令(尤其是 SCASB),就好像你的生命依赖于它们一样。你在任何地方都使用了这些,你把事情复杂化了很多。

举个例子,这就是白色space跳绳应该做的:

@separators_loop:
    lodsb
    cmp al, " "
    loope @separators_loop
    jz @exit
@word_begin:

现在呢?

要使这项工作正常进行,您需要先简化任务。

  1. 获取用户的输入
  2. 从此输入中提取单个单词
  3. 在屏幕上回显这个词,后跟一个 space 字符
  4. 重复步骤 2 和 4 直到 CX=0

然后为了完成原始任务,您在 2 和 4 之间插入了一个额外的步骤来验证单词。如果没有,则直接进行第5步

  1. 获取用户的输入
  2. 从此输入中提取单个单词
  3. 检查是否按字母顺序排列,如果不是则转到第 5 步
  4. 在屏幕上回显这个词,后跟一个 space 字符
  5. 重复步骤 2、3 和 4 直到 CX=0