assemblyx86ascii

How to access a char array and change lower case letters to upper case, and vice versa


I'm currently working on a class project for Structured Computer Organization using an x86 processor. The value that I am accessing is an 1 byte char, but I do not know how to compare it to an uppercase. They said to use an ASCII table of the hex format, but I'm not sure how to even compare the two.

void changeCase (char char_array[], int array_size ) {
    __asm {
            // BEGIN YOUR CODE HERE
 
        mov eax, char_array;        //eax is base image
        mov edi, 0;
        
    readArray:
        cmp edi, array_size;
        jge  exit;
        mov ebx, edi;           //using ebx as offset
        shl ebx, 2;
        mov cl, [eax + ebx];    //using ecx to be the storage register
    
    check:
        //working on it
        cmp cl, 0x41;       //check if cl is <= than ASCII value 65 (A)
        jl next_indx;
        cmp cl, 0x7A;       //check if cl is >= than ASCII value 122 (z)
        jg next_indx;
        cmp cl, 'a';
        jl convert_down;
        jge convert_up;
        

    convert_down:
        or cl, 0x20;        //make it lowercase
        jmp write;

    convert_up:
        and cl, 0x20;       //make it uppercase
        jmp write;

    write:
        mov byte ptr [eax + ebx], cl    //slight funky town issue here,

    next_indx:
        inc edi;

    exit:
        cmp edi, array_size;
        jl readArray;

    mov char_array, eax;
            // END YOUR CODE HERE
    }
}

Anything helps at this point. Thank you in advance for the help!

edit 1:

Thanks for all the suggestion and points of clarity, edited my code to reflect change. Some problem with access violation now.

edit 2 (+):

Thanks for the helpful eyes people. I'm still getting to translating all letters now.


Solution

  • For clarity's sake, I'll just use pure assembly and assume that...

    You should be able to deduce this yourself into inline assembly. Now, if you look at the table everyone is supposed to remember but barely anyone does, you'll notice some important details...

    As a result, the algorithm would be...

    while array_size != 0
        byte = *char_array
        if byte >= 0x41 and byte <= 0x5A
            *char_array |= 0x20 // Turn it lowercase
        else if byte >= 0x61 and byte <= 0x7A
            *char_array &= 0xDF // Turn it uppercase
        array_size -= 1
        char_array += 1
    

    Now, let's translate this into assembly...

    mov eax, [ebp+8]      # char *eax = char_array
    mov ecx, [ebp+12]     # int ecx = array_size
    
    .loop:
        or ecx, ecx       # Compare ecx against itself
        jz .end_loop      # If ecx (array_size) is zero, we're done
        mov dl, [eax]     # Otherwise, store the byte at *eax (*char_array) into `char dl`
        cmp dl, 'A'       # Compare dl (*char_array) against 'A' (lower bound of uppercase letters)
        jb .continue      # If dl` (*char_array) is lesser than `A`, continue the loop
        cmp dl, 'Z'       # Compare dl (*char_array) against 'Z' (upper bound of uppercase letters)
        jbe .is_uppercase # If dl (*char_array) is lesser or equal to 'Z', then jump to .is_uppercase
        cmp dl, 'a'       # Compare dl (*char_array) against 'a' (lower bound of lowercase letters)
        jb .continue      # If dl (*char_array) is lesser than 'a', continue the loop
        cmp dl, 'z'       # Compare dl (*char_array) against 'z' (upper bound of lowercase letters)
        jbe .is_lowercase # If dl (*char_array) is lesser or equal to 'z', then jump to .is_lowercase
        jmp .continue     # All tests failed, so continue the loop
    
        .is_uppercase:
            or dl, 20h    # Set the 6th bit
            mov [eax], dl # Send the byte back to where it came from
            jmp .continue # Continue the loop
    
        .is_lowercase:
            and dl, DFh   # Clear the 6th bit
            mov [eax], dl # Send the byte back to where it came from
            jmp .continue # Continue the loop
    
        .continue:
            inc eax       # Increment `eax` (`char_array`), much of like a pointer increment
            dec ecx       # Decrement `ecx` (`array_size`), so as to match the previous pointer increment
            jmp .loop     # Continue
    
    .end_loop:
    

    Once code reaches .end_loop, you're done.

    I hope this has led a light on you!