【问题标题】:Assembly emu8086, reversing a string组装emu8086,反转一个字符串
【发布时间】:2017-12-08 01:30:47
【问题描述】:

我正在尝试制作一个用户必须输入字符串并获得反向输出的程序。此外,它应该将所有小写字母变为大写,将大写变为小写。我已经完成了可以输入 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,它将返回olleHh。我完全困惑,因为我无法弄清楚我的错误。另外,我是大会的新手。我期望的输出是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 循环中发生了什么? PS:注释你的代码,特别是如果你想让别人理解它(它也可以帮助你发现你自己的错误)。
  • @Jester 非常感谢。会听从你的建议!
  • 相关:case flip an ASCII string (skipping non-alphabetic characters)。在反向循环中使用该逻辑。
  • 在很START:你有废话cmp al, 0x41hJGE IsInLowerCaseRange没有任何评论,它应该做什么。它表明您根本不了解源代码中的内容,而且如果没有您的 cmets(显示您的人类意图),就不可能看到您为什么不理解它,以及您的实际错误是什么。你刚刚忘记加载al了吗?你相信mov ax,@DATA 是魔法,它会为你的al 加载字符值吗?等等... 使用 emu8086 内置调试​​器缓慢地跳过单个指令,并推理它们中的每一个,它为什么存在以及它的作用。
  • 仅仅运行您的代码并在屏幕上接收正确的输出肯定不足以验证您的代码。即使代码包含基本问题,并且几乎每次其他输入更改都会中断,您也可以通过纯粹的运气和意外多次获得正确的输出。仔细调试添加到代码中的每条指令并对其进行推理,是正确验证汇编代码的唯一方法。

标签: assembly reverse uppercase lowercase emu8086


【解决方案1】:

你让事情变得复杂了。

首先,您使用以下代码以相反的顺序显示字符串的所有字母:

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 10H

0EH 服务

为什么你的输出字符串末尾会有多余的 h 字母?

您正在使用INT 10h,它用于视频服务,并且INT 10h 的服务0EH 将AL 中的指定字符写入当前光标位置。由于 AL 中的最后一个字符在您的示例中是大写 H 并且您的代码将其翻转为小写 h。这就是您在输出字符串末尾获得额外的 h 的地方。

你为什么不把所有的字母都翻过来?

由于INT 10h 的服务0EH 只向屏幕写入一个字符(而不是字符串),因此您只得到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 所说,您应该在程序中使用注释,因为这可以解释您在程序中尝试执行的操作,并使人们可以轻松调试它。

【讨论】:

  • 那么这是一个糟糕的答案,因为您只是发布了代码转储,而没有解释您更改了哪些部分或原因。如果您不打算这样做,您不妨只发布没有来自 OP 的所有笨重内容的良好工作代码。
  • 哦,我现在也看到了sub。与无条件的xor 相比,方式过于复杂,但还可以。 OP 的代码已经在尝试以愚蠢的方式进行操作。
  • 是的,看起来还是更好。当你知道你可以detect if a byte is an ASCII alphabetic character in 4 instructions with one branch 时,读起来仍然很痛苦。不过,我知道你只是想坚持 OP 的设计。
  • 这不是我的,但可能是因为代码块之外几乎没有任何文字说明出了什么问题或您更改了什么。
  • 现在你的答案很好。我没有非常仔细地阅读 OP 的代码,直到你上次更新它打印的真正原因还不清楚,但现在它是。现在非常有意义,因为它反转了字符串,然后打印了一个大小写翻转的字符。清楚地解释它实际上做了什么很重要。 (不过,这仍然是一个无聊的调试问题;不要指望其他人会投很多票!)
猜你喜欢
  • 2021-12-19
  • 2016-01-06
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
相关资源
最近更新 更多