反转句子的单词字母,保持与在 emu8086 中输入的词序相同
Reverse word letters of a sentence with keeping same word order as entered in emu8086
我需要用 emu8086
用汇编语言编写一个程序,它需要一个句子(包括 space/blank)并根据以下条件给出输出:
- 以与输入相同的词序显示文本,但每个词中的字母颠倒。
- 示例“
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为奇数时,中间的字符留在原来的位置(原位)。
我需要用 emu8086
用汇编语言编写一个程序,它需要一个句子(包括 space/blank)并根据以下条件给出输出:
- 以与输入相同的词序显示文本,但每个词中的字母颠倒。
- 示例“
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为奇数时,中间的字符留在原来的位置(原位)。