问题
I am trying to make a program where the user have to enter a string and get an reversed output. Moreover, it should change all lowercase letters to uppercase and uppercase to lowercase. I've already done program where you can enter 1 character. My next goal is to get as many characters as I want.
I did some research and came up with this code:
org 100h
include emu8086.inc
.DATA
STR1 DB 0DH,0AH, 'Input: $'
STR2 DB 0DH,0AH, 'Output: $'
nl db 0dh,0ah,'$'
.CODE
START:
MOV AX, @DATA
MOV DS, AX
cmp al, 0x41h
JGE IsInLowerCaseRange
Disp:
LEA DX,STR1
MOV AH,09H
INT 21H
MOV CL,00
MOV AH,01H
Read:
INT 21H
MOV BL,AL
PUSH BX
inc cx
CMP AL,0DH
JZ DISPLAY
JMP READ
Display:
LEA DX,STR2
MOV AH,09H
INT 21H
lea dx, nl
mov ah,09h
int 21h
ANS:
MOV AH,02H
POP BX
MOV DL,BL
INT 21H
LOOP ANS
IsInLowerCaseRange:
cmp al, 0x5Ah
jle DisplayLowerCaseLetter
cmp al, 0x61h
jge IsInUpperCaseRange
jmp NotALetter
DisplayLowerCaseLetter:
add al, 0x20h
mov ah, 0xEh
int 10h
jmp exit
IsInUpperCaseRange:
cmp al, 0x7Ah
jle DisplayUpperCaseLetter
jmp NotALetter
DisplayUpperCaseLetter:
sub al, 0x20h
mov ah, 0xEh
int 10h
jmp exit
NotALetter:
printn
print "The input character is not a letter."
exit:
hlt
.EXIT
END START
Now I am getting a wrong output. For example if you enter Hello
it will return olleHh
. I am completely confused since I can't figure out my error. Also, I am new in Assembly. The output that I expect is OLLEh
.
Working Code:
org 100h
include emu8086.inc
.DATA
STR1 DB 0DH, 0AH, 'Input: $'
STR2 DB 0DH, 0AH, 'Output: $'
Nl DB 0Dh, 0Ah,'$'
.CODE
START:
MOV AX, @DATA
MOV DS, AX
DISP:
LEA DX,STR1
MOV AH,09H
INT 21H
MOV CL,00
MOV AH,01H
READ:
INT 21H
MOV BL, AL
PUSH BX
INC CX
CMP AL, 0DH
JZ DISPLAY
CMP AL, 'A' ; < then A
JB NotALetter
CMP AL, 'Z' ; > then Z
JA AGAIN ; repeat again
JMP CONTINUE1
AGAIN:
CMP AL, 'a' ; < then a
JB NotALetter
CMP AL, 'z' ; > then z
JA NotALetter
CONTINUE1:
JMP READ
DISPLAY:
LEA DX, STR2
MOV AH, 09h
INT 21H
LEA DX, NL
MOV AH, 09h
INT 21h
POP BX ; pop enter key
ANS:
MOV AH, 02h
POP BX ; pop the character
CMP BL, 'a' ; check if its in upper case
JB toLower ; if yes then jmp to toLower
SUB BL, 32 ; if not in upper case then convert to upper case
JMP CONTINUE2
toLower:
ADD BL, 32 ; convert to lower case
; Probably have to subtract 32 if BL = 20h
CONTINUE2:
MOV DL, BL
INT 21H
LOOP ANS
JMP EXIT ; if everything is fine jmp to exit
NotALetter:
printn
print "The input character is not a letter."
EXIT:
hlt
.EXIT
END START
回答1:
You are making it complex.
First you display all the letters of your string in reverse order with the following code:
ANS:
MOV AH,02H
POP BX
MOV DL,BL
INT 21H
LOOP ANS
and then you try to flip the cases with the following code:
IsInLowerCaseRange:
cmp al, 0x5Ah
jle DisplayLowerCaseLetter
cmp al, 0x61h
jge IsInUpperCaseRange
jmp NotALetter
DisplayLowerCaseLetter:
add al, 0x20h
mov ah, 0xEh
int 10h
jmp exit
IsInUpperCaseRange:
cmp al, 0x7Ah
jle DisplayUpperCaseLetter
jmp NotALetter
DisplayUpperCaseLetter:
sub al, 0x20h
mov ah, 0xEh
int 10h
Problem is with using 0EH service of INT 10H
Why do you get that extra h letter at the end of your output string ?
You are using INT 10h which is used for video services and the service 0EH of INT 10h writes the specified character in AL to the current cursor position. Since the last character in AL was capital H in your example and which was flipped to lower case h by your code. That is where you get that extra h at the end of your output string.
Why don't you get all the letters flipped ?
Since the service 0EH of INT 10h writes only one character to the screen (not the string) you get only H to be flipped.
Solution:
You could have simply flipped the cases and displayed the reverse string in one go and that without using INT 10h.
Here is a simple code which is well documented and that does the job:
org 100h
.DATA
str1 db 10,13, 'Input: $'
str2 db 10,13, 'Output: $'
errMsg db 10,13, 'The input character is not a letter.$'
.CODE
START:
mov ax, @DATA
mov ds, ax
mov dx, offset str1
mov ah, 09h
int 21h
mov cl,00
mov ah,01h
mov bx, '#' ; store some random character
; into stack to remeber when to stop
push bx ; poping the character while diplaying
Read:
int 21h
cmp al, 13 ; check if enter key is pressed
je DISPLAY ; if yes then display the letters if any
cmp al, 'A' ; check if ASCII value of inputted charater is less than ASCII value of capital A
jb NotALetter ; if yes then print "no a letter"
cmp al, 'Z' ; check if ASCII value of inputted charater is not greater than ASCII value of capital Z
jna letterFound ; if not then continue
cmp al, 'a' ; check if ASCII value of inputted character is less than ASCII value of small a
jb NotALetter ; if yes then print "no a letter"
cmp al, 'z' ; check if ASCII value of inputted character is greater than ASCII value of small z
ja NotALetter ; if not then continue
letterFound:
mov bl, al
push bx ; store the letter in stack
jmp READ
Display:
mov dx,offset str2
mov ah,09h
int 21h
ANS:
pop bx
cmp bl, '#' ; check if no more letter are available in stack
je exit
mov ah, 02h
cmp bl, 'a' ; check if the letter is in upper case
jb toLower ; if yes then jmp to toLower
sub bl, 32 ; if not in upper case then convert to upper case
jmp continue
toLower:
add bl, 32 ; convert to lower case
continue:
mov dl, bl
int 21h
jmp ans
NotALetter:
mov ah, 09h
mov dx, offset errMsg ; display error message
int 21h
exit:
mov ah, 04ch
int 21h
END START
And as @Ped7g said you should use comment in your program because that explain what you are trying to do in your program and makes it easy for people to debug it.
来源:https://stackoverflow.com/questions/47706414/assembly-emu8086-reversing-a-string