反转句子的单词字母,保持与在 emu8086 中输入的词序相同

Reverse word letters of a sentence with keeping same word order as entered in emu8086

我需要用 emu8086 用汇编语言编写一个程序,它需要一个句子(包括 space/blank)并根据以下条件给出输出:

  1. 以与输入相同的词序显示文本,但每个词中的字母颠倒
  2. 示例“hello world”输入给出输出:“olleh dlrow

我尝试使用以下代码:

.MODEL SMALL
.STACK 100H
.DATA

; The string to be printed
STRING DB 'This is a sample string', '$'

.CODE
MAIN PROC FAR
MOV AX,@DATA
MOV DS,AX

; call reverse function
CALL REVERSE

; load address of the string
LEA DX,STRING

; output the string
; loaded in dx
MOV AH, 09H
INT 21H

; interrupt to exit
MOV AH, 4CH
INT 21H

MAIN ENDP
REVERSE PROC
    ; load the offset of
    ; the string
    MOV SI, OFFSET STRING

    ; count of characters of the;
    ;string
    MOV CX, 0H

    LOOP1:
    ; compare if this is;
    ;the last character
    MOV AX, [SI]
    CMP AL, '$'
    JE LABEL1

    ; else push it in the;
    ;stack
    PUSH [SI]

    ; increment the pointer;
    ;and count
    INC SI
    INC CX

    JMP LOOP1

    LABEL1:
    ; again load the starting;
    ;address of the string
    MOV SI, OFFSET STRING

        LOOP2:
        ;if count not equal to zero
        CMP CX,0
        JE EXIT

        ; pop the top of stack
        POP DX

        ; make dh, 0
        XOR DH, DH

        ; put the character of the;
        ;reversed string
        MOV [SI], DX

        ; increment si and;
        ;decrement count
        INC SI
        DEC CX

        JMP LOOP2

                
    EXIT:
    ; add $ to the end of string
    MOV [SI],'$ '
    RET
        
REVERSE ENDP
END MAIN

但这会颠倒整个句子(不要保持相同的词序)。像“hello world”输入给出“dlrow olleh”输出。

请建议我该如何解决这个问题?

您正确地使用了过程 REVERSE 来反转整个 STRING。当您需要分别反转 STRING 的每个词汇时,您应该类似地拆分任务: 将输入字符串解析为单词并将子过程 ReverseWord 应用于每个这样的单词。

将任务划分为更小的子过程使得更容易理解并且更容易调试。如有必要,您可以稍后尝试优化它。

REVERSE PROC                ; Reverse words in STRING.
          LEA SI,[STRING]
          CLD               ; LODSB will parse forward.
NextWord: MOV DI,SI         ; Let SI=DI=at the first char of the word.
NextChar: LODSB             ; Load AL from [SI], increment SI.
          CMP AL," "        ; Search for white-space terminator.
          JBE WordEnd
          CMP AL,"$"        ; $ terminates the word, too.
          JE StringEnd
          JMP NextChar      ; Repeat when the word is not terminated yet.
WordEnd:  CALL ReverseWord  ; Reverse the word between DI and SI.
          JMP NextWord
StringEnd:CALL ReverseWord  ; Reverse the last word between DI and SI.
          RET               ; All words are reversed in situ.
        ENDP

ReverseWord PROC            ; Reverse the word between DI and SI-1.
     PUSHAW                 ; Do not clobber any register.
      DEC SI                ; Let SI=behind the last char of the word.
      MOV CX,SI
      SUB CX,DI             ; Let CX=number of chars in the word.
      SHR CX,1              ; Divide CX in half, ignore remainder.
      JZ Done               ; Do nothing when the word is 1 char or less.
Again:DEC SI                ; Let SI=at the last char of the word.
      MOV AL,[SI]           ; Load AL with the last char.
      MOV DL,[DI]           ; Load DL with the first char.
      MOV [SI],DL           ; Swap the first and the last chars.
      MOV [DI],AL
      INC DI
      LOOP Again            ; Repeat with the inner chars.
Done:POPAW                  ; Restore all registers.
     RET                    ; The word between DI..SI was reversed.
    ENDP

内部子过程ReverseWord被使用了两次,字符串终止符$保持原样原位 . 注意字符交换的个数是word size的一半,word size为奇数时,中间的字符留在原来的位置(原位)。