Search code examples
x86inline-assemblymasm

Converting lowercase character string to uppercase masm


there is a printf statement which tells the compiler to print outStr. outStr is originally set to equal emptybuf[1000] = "??? not translated yet ???";. I am supposed to move my answer into the outStr, which should update the outStr in the print statement.

For some reason my inline assembly will not print out anything from the code shown below. I cannot understand what I am doing wrong. I am trying to convert lowercase letters to uppercase, and ignore any special characters. Any advice is much appreciated.

mov esi,inStr ;To start off initialize  esi point to input string
mov edi,outStr  ;edi point to the output string area

    ; using esi and edi with [esi] and [edi] as indirect operand

    ; suggestion  to start mov each character to al  like   -->  mov al,[esi]
    ; test, and manipulate character in al


        jmp getNext         
getNext: mov al,[esi]
    cmp al,0
 je exitProc
        test al,01100000b ;test to see if its a lowercase letter
        je toUpperCase
        test al,01000000b
        mov [edi],al
        inc esi
toUpperCase: test al,01000000
         AND al,11011111b
         mov [edi],al
         inc esi
         jmp getNext
exitProc: mov outStr, edi

Solution

  • There is a lot wrong here, so I'll try and explain each section separately.

    First, the test for lowercase (testing 01100000b) isn't going to work. It'll never be zero, for either case, since they both have the 6th bit set.

    If think the only way to make sure you're only uppercasing 'a' to 'z' is to explicitly compare for characters in that range. So your first test becomes something like this:

        cmp al,'a'
        jl noChange
        cmp al,'z'
        jle toUpperCase
    noChange:
        mov [edi],al
        ...
    

    Then the additional test al,01000000b you had before mov [edi],al does nothing, so that can be removed.

    And once you've copied the character in the branch that is already uppercase, you should be jumping to the top of the loop, otherwise you're going to fall through to the toUpperCase branch and store the character a second time.

    Also you should be incrementing edi, otherwise you're going to write to the same position over and over again.

        mov [edi],al
        inc edi     ; You need to add this
        inc esi
        jmp getNext ; You need to add this
    

    Same thing goes for the toUpperCase branch. You need to increment edi, and again you have a test there that does nothing.

    toUpperCase:
         AND al,11011111b
         mov [edi],al
         inc edi   ; Add this
         inc esi
         jmp getNext
    

    Finally, when exiting, you need to add a NULL to the end of the outStr. And there is no need to assign edi back to outStr, especially since it is now pointing to the end of the string.

    exitProc:
         mov [edi],0
    

    Now this could be made more efficient, in that you have a lot of repeated code as well. But that is all that has to be done to get it working.