Search code examples
assemblyproceduremasm

toUpper procedure in MASM?


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

Solution

  • 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