Assembly emu8086, reversing a string

对着背影说爱祢 提交于 2019-12-11 07:15:22

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!