0

I am trying to write a trivial toUpper procedure in MASM for ASCII only. It works, however, whenever it encounters a whitespace character, it wont continue changing the case of that character and the ones following it. I can't figure out the reason why this is happening. So what I did is put a conditional statement to test if a character is a space ' ' (32) and thus jump beyond it. Is this enough or should I test for any value that is not between 97 and 122 also?

    ; EDX - INPUT - The offset to the BYTE Array 
    ; ECX - INPUT - The Size of the BYTE Array 
    ; EDX - OUTPUT- The offset to the new BYTE Array toUpper PROC
    PUSH ECX                ; we will modify this so push it to the stack
    DEC  ECX                ; we don't want the null terminating char
    loopMe:         
        MOV  AL, [EDX]      ; otherwise move what the EDX points to to AL       
        CMP  AL, 32         
        JNE  goodChar       
        INC  EDX            ; increment the pointer by one byte since this is a space       
        loop  loopMe        ; go to the next char
        goodChar:           
            AND  AL   , 11011111b  ; make AL capital            
            MOV  [EDX], AL          
            INC  EDX               ; increment the pointer by one byte          
            LOOP loopMe 
    done:
        POP ECX                        ; return it back to its original value
        RET toUpper ENDP
Seek
  • 27
  • 1
  • 5
  • 2
    One bug in your code is that if the last character in the string is a space, then you'll fall into the `goodChar` part and execute those instructions. Note also that there's no point in writing ASCII codes directly; the assembler understands `CMP AL, ' '` just fine. – Michael Aug 12 '21 at 11:05
  • 1
    Only lower case characters should cause the logic to reach `goodChar`. Instead of `CMP AL, 32` and what comes immediately after, you could do `cmp al, 'a'; jb skip; cmp al,'z'; ja skip`, and then `skip:` would be before the currently second `INC EDX` in your code. – 500 - Internal Server Error Aug 12 '21 at 12:37
  • See [What is the idea behind ^= 32, that converts lowercase letters to upper and vice versa?](https://stackoverflow.com/a/54585515) for a better asm algorithm for checking for alphabetic characters. See also [Convert a String In C++ To Upper Case](https://stackoverflow.com/a/37151084) for the logic and [How to access a char array and change lower case letters to upper case, and vice versa](https://stackoverflow.com/a/35936844) for similar logic in assembly that's more efficient than two separate cmp/jb cmp/ja checks. – Peter Cordes Aug 12 '21 at 12:45

1 Answers1

2

You have a problem after the first LOOP instruction:

    PUSH ECX
    DEC  ECX
loopMe:         
    MOV  AL, [EDX]
    CMP  AL, 32
    JNE  goodChar
    INC  EDX
    LOOP loopMe
                   <--- what happens here?
    goodChar:
        AND  AL   , 11011111b
        MOV  [EDX], AL
        INC  EDX
        LOOP loopMe
done:
    POP ECX
    RET toUpper

There are two solutions here, either jump to the second LOOP or jump to the done: label after the first loop. Also, you should really only apply the upper "trick" to 'a-z', which means the CMP AL,... would test against 'a', if smaller, jump to the loop, then test again against 'z', if larger, jump to the loop.

    PUSH ECX
    DEC  ECX
loopMe:         
    MOV  AL, [EDX]
    CMP  AL, 'a'
    JL   next
    CMP  AL, 'z'
    JG   next
    AND  AL   , 11011111b
    MOV  [EDX], AL
next:
    INC  EDX
    LOOP loopMe 
done:
    POP ECX
    RET toUpper
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • "There are **two** solutions here, either jump to the second LOOP (instruction)..." This would immediately start a 4GB loop! The **only** solution was to jump to the *done:* label. – Sep Roland Aug 25 '21 at 19:21
  • @SepRoland What I meant is instead of a first `LOOP ...` it would be to jump to the second `LOOP ...` which is more or less what I show in my fixed sample. I guess there are many other solutions, as the one you propose which is to jump after the `LOOP ...` to the `done:` label. – Alexis Wilke Aug 25 '21 at 22:51