组装emu8086,反转字符串
Assembly emu8086, reversing a string
我正在尝试制作一个程序,用户必须在其中输入字符串并获得反向输出。此外,它应该将所有小写字母更改为大写字母,将所有大写字母更改为小写字母。我已经完成了可以输入 1 个字符的程序。我的下一个目标是获得尽可能多的角色。
我做了一些研究并想出了这个代码:
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
现在我得到一个错误的输出。例如,如果您输入 Hello
,它将 return olleHh
。我完全困惑,因为我无法弄清楚我的错误。另外,我是 Assembly 的新手。我期望的输出是 OLLEh
.
工作代码:
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
你把它弄复杂了。
首先,使用以下代码以相反的顺序显示字符串中的所有字母:
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
问题在于使用 INT 0EH 服务 10H
为什么在输出字符串的末尾会出现额外的 h 字母?
您正在使用 INT 10h which is used for video services and the service 0EH of INT 10h 将 AL 中的指定字符写入当前光标位置。由于 AL 中的最后一个字符在您的示例中是大写字母 H 并且您的代码将其翻转为小写字母 h 。这就是您在输出字符串末尾获得额外 h 的地方。
你为什么不把所有的字母都翻转过来?
由于服务 0EH of INT 10h 只向屏幕写入一个字符(不是字符串),因此您只能翻转 H。
解法:
您可以简单地翻转大小写并一次显示反向字符串,而无需使用 INT 10h。
这是一个简单的代码,它有很好的文档记录并且可以完成这项工作:
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
正如 @Ped7g 所说,您应该在程序中使用注释,因为这可以解释您在程序中尝试做什么,并使人们可以轻松调试它。
我正在尝试制作一个程序,用户必须在其中输入字符串并获得反向输出。此外,它应该将所有小写字母更改为大写字母,将所有大写字母更改为小写字母。我已经完成了可以输入 1 个字符的程序。我的下一个目标是获得尽可能多的角色。
我做了一些研究并想出了这个代码:
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
现在我得到一个错误的输出。例如,如果您输入 Hello
,它将 return olleHh
。我完全困惑,因为我无法弄清楚我的错误。另外,我是 Assembly 的新手。我期望的输出是 OLLEh
.
工作代码:
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
你把它弄复杂了。
首先,使用以下代码以相反的顺序显示字符串中的所有字母:
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
问题在于使用 INT 0EH 服务 10H
为什么在输出字符串的末尾会出现额外的 h 字母?
您正在使用 INT 10h which is used for video services and the service 0EH of INT 10h 将 AL 中的指定字符写入当前光标位置。由于 AL 中的最后一个字符在您的示例中是大写字母 H 并且您的代码将其翻转为小写字母 h 。这就是您在输出字符串末尾获得额外 h 的地方。
你为什么不把所有的字母都翻转过来?
由于服务 0EH of INT 10h 只向屏幕写入一个字符(不是字符串),因此您只能翻转 H。
解法:
您可以简单地翻转大小写并一次显示反向字符串,而无需使用 INT 10h。
这是一个简单的代码,它有很好的文档记录并且可以完成这项工作:
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
正如 @Ped7g 所说,您应该在程序中使用注释,因为这可以解释您在程序中尝试做什么,并使人们可以轻松调试它。