反转和更改给定字符串x86程序集的大小写 [英] Reversing and changing case of a given string x86 assembly

查看:58
本文介绍了反转和更改给定字符串x86程序集的大小写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该程序的目的是在切换每个字母的大小写的同时反转给定的字符串.字符串不能超过20个字符,如果输入长度超过20个字符,则程序要求用户再次输入字符串.程序在用户输入"enter"时结束,并且在打印结束语句后结束.

The objective of this program is to reverse a given string while switching each letter's case. String cannot be longer than 20 characters, if input is longer than that, program requires user to enter string again. Program ends when user inputs 'enter' and the program ends after printing an ending sentence.

为此,我有3个问题:

  1. 我试图通过调用ReadString来获取输入字符串,并且由于在输入Enter键后此过程停止,因此当我按Enter键正常完成程序时,控制台冻结结束.如何纠正我的代码以使其显示结束消息,然后正常地以返回值0结束程序?

  1. I tried to get input string by using call ReadString and since this procedure stops when enter key is given, the console freeze-ends when I press the enter key to normally finish the program. How could I correct my code to make it print an ending message and then end the program normally with return value 0?

如果输入字符串长于20个字符,则应要求用户再次输入字符串.所以我写了ja L1.出于某种原因,bur,mov字节数,eax;cmp bytecount,20;似乎无法正确过滤情况.当行mov bytecount,eax被执行时,bytecount的值正确,但是当程序执行下一行cmp bytecount,20时,bytecount的值改变.我不知道我在做什么错.

If input string is longer than 20 characters, it should require user to input string again. So I wrote ja L1. Bur for some reason, mov bytecount, eax; cmp bytecount, 20; cannot seem to filter the case properly. When the line mov bytecount, eax is executed, the value of bytecount is correct, but when the program executes the next line, cmp bytecount, 20, the value of bytecount changes. I don't know what I'm doing wrong.

CaseChange过程在执行时冻结,因此我想它无限循环,但是我找不到什么条件是错误的.

CaseChange procedure freezes when it is executed, so I guess it's looping infinitely, but I can't find what condition is wrong.

.data
MaxLength = 20
prompt3 BYTE "End of program",0
buffer BYTE MaxLength DUP(0)
bytecount DWORD ?

.code 
main PROC
    call Clrscr
L1: mov edx, OFFSET buffer
    mov ecx, SIZEOF buffer
    call PromptForInput     ; printing input prompt
    call ReadString      
    mov bytecount, eax
    cmp bytecount, 20       ;*** get input again if number of characters in the string is greater than 20
    ja L1                   ;*** 
    call ReverseString     
    call CaseChange         ;***
    mov edx, OFFSET buffer
    call WriteString        ;printing the result
    loop L1
    mov edx, OFFSET prompt3 ;*** after input <ent> how do I print prompt3?
    call WriteString
    exit
main ENDP

CaseChange PROC
    pushad 
    mov eax, OFFSET buffer
L1:
    mov dl, BYTE PTR[eax]
    test dl, dl
    jz L3
    cmp dl, 'A'
    jl L3
    xor dl,32
    cmp dl,'z'
L2:
    inc eax
    jmp L1
L3:
    popad
    ret
CaseChange ENDP

(输入提示):猫和狗.

(input prompt): Cats and Dogs.

(输出提示):.SGOd DNA STAc

(output prompt): .SGOd DNA STAc

(输入提示):对于给定的限制太长了

(input prompt): too long for the given limit

(输入提示):

程序结束

推荐答案

手册为我们介绍了 ReadString :

从标准输入中读取最多包含ECX个非空字符的字符串,并在用户按下Enter键时停止.
在输入的字符之后会存储一个空字节,但是尾随回车符和换行符不会放入缓冲区.
ECX应该始终小于缓冲区大小(永远不等于缓冲区大小),因为空字节可能是存储的第(ECX + 1)个字符.

Reads a string of up to ECX non-null characters from standard input, stopping when the user presses the Enter key.
A null byte is stored following the characters input, but the trailing carriage return and line feed characters are not placed into the buffer.
ECX should always be smaller than the buffer size (never equal to the buffer size) because the null byte could be the (ECX+1)th character stored.

在此之后,很明显,您需要扩大缓冲区:

Following this it's clear to see that you need to enlarge the buffer:

buffer BYTE MaxLength + 1 DUP (0)

如果您指定了 ECX = MaxLength ,则输入的字符数不能超过 MaxLength 个字符,因此没有必要真正测试这种情况.(*)

If you specified ECX=MaxLength then you can't get an input that is longer than MaxLength characters and thus there's no real need to test for such condition. (*)

如果用户按下 enter 键且没有前面的字符,则 ReadString 将返回 EAX = 0 .对此进行测试,然后跳至您的最终消息.

If the user presses the enter key with no preceeding characters, then ReadString will return with EAX=0. Test this and jump to your final message.

一个大错误是您编写 loop L1 的位置. loop 指令与 ECX 寄存器一起执行已知的迭代次数.您的程序只需要跳回顶部即可,没有附加任何条件.使用 jmp L1 .

A big error is where you wrote loop L1. The loop instruction works with the ECX register to perform a known number of iterations. Your program needs to just jump back to the top with no conditions attached. Use jmp L1.

最好在逻辑上保持一致.不要将 call PromptForInput call ReadString 及其参数混合使用.您可以确定 PromptForInput 不会更改 EDX ECX 吗?

It's best if you keep things logically together. Don't mix call PromptForInput with call ReadString and its parameters. Can you be sure that PromptForInput doesn't change EDX or ECX?

L1: call    PromptForInput

    mov     edx, OFFSET buffer
    mov     ecx, MaxLength
    call    ReadString         ; -> EAX
    test    eax, eax
    jz      L2                 ; Exit

    call    ReverseString       ; Is this working fine?
    call    CaseChange

    mov     edx, OFFSET buffer
    call    WriteString         ; Printing the result

    jmp     L1

L2:
    mov     edx, OFFSET prompt3
    call    WriteString         ; Final message

    exit


  • cmp dl,'A' jl L3 ChangeCase 过程需要遍历整个字符串,但是一旦偶然发现小于65的字节,您便会离开.使用ASCII码时,请使用 unsigned 条件[0,255].


    • cmp dl, 'A' jl L3 The ChangeCase procedure needs to traverse the whole string, yet you leave as soon as you stumble upon a byte less than 65. Please use the unsigned condition when working with ASCII codes [0,255].

      xor dl,32 您实际上并没有在字符串存储器中写入任何更改.

      xor dl,32 You don't actually write any changes in the string memory.

      cmp dl,'z'您不对此比较采取行动.

      cmp dl,'z' You don't act on this compare.

      如果您需要保留的只是1个寄存器,请不要使用 pushad popad .

      If all you need to preserve is 1 register then don't use pushad and popad.

      CaseChange PROC
          push    esi
          mov     esi, OFFSET buffer
      L1:
          lodsb
          test    al, al        ; End of string ?
          jz      L2
          or      al, 32        ; If "A".."Z" Then "a".."z"
          cmp     al, 'a'
          jb      L1
          cmp     al, 'z'
          ja      L1
          xor     byte ptr [esi-1], 32  ; Change case IN string memory
          jmp     L1
      L2:
          pop     esi
          ret
      CaseChange ENDP
      


      (*)如果要强加此字符串不能超过20个字符"错误,则定义一个更大的缓冲区,并允许 ReadString 返回超过20个字符,以便您可以跳回该程序:


      (*) If you want to impose this "String cannot be longer than 20 characters" error then define a much bigger buffer and allow ReadString to return more than 20 characters so you can jump back in the program:

      buffer BYTE 99 + 1 DUP (0)
      
      ...
      
      L1: call    PromptForInput
      
          mov     edx, OFFSET buffer
          mov     ecx, 99
          call    ReadString         ; -> EAX
          cmp     eax, 20
          ja      L1
          test    eax, eax
          jz      L2                 ; Exit
      


      最后的建议是通过独立测试 ReverseString CaseChange 正常:

          call    ReverseString
          ;;;call    CaseChange
          mov     edx, OFFSET buffer
          call    WriteString         ; Printing the result
      

      及以后

          ;;;call    ReverseString
          call    CaseChange
          mov     edx, OFFSET buffer
          call    WriteString         ; Printing the result
      

      只有这样

          call    ReverseString
          call    CaseChange
          mov     edx, OFFSET buffer
          call    WriteString         ; Printing the result
      

      这篇关于反转和更改给定字符串x86程序集的大小写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆