What Is the Idea Behind ^= 32, That Converts Lowercase Letters to Upper and Vice Versa

How to convert lower case to upper case and vice versa without using subtraction or addition in emu8086

This is an interesting observation that if you look into ascii a~z's binary value, you'll see that all of them have the 6th bit set to 1. and all ascii A~Z's 6th bit is set to 0. And remaing all bits are same. Check it out:

a = 01100001          z = 01111010
A = 01000001 Z = 01011010
^ ^

Now, 6th bit binary value is 32 (00100000) . So, if we can do xor operation with lower case or upper case letter then it will convert. Easy thing to remember: 32d is related to upper to lower Or lower to upper. Here is the demo code:

; Here at first, @ indicating start of label and $ indicating start of procedure.
; If multiple label and procedure is present in assembly code.
; Then distinguishing label & procedure can be done easily.
; It's just my own way of coding. You may ignore this style.

.model small ; declaring this code will be consists of one data segment and one code segment
.stack 100h ; stack is initializeed to offset address at 100h

.data ; starting of Data segment

n_line db 0ah,0dh,"$" ; for new line
input_msg db "Input",20h,": $" ; 20h = 32d = ascii 'space'
output_msg db 0ah,0dh,"Output: $"
stop_msg db "Press 'esc' to Stop this Programme.",0ah,0dh,"$"
end_msg db 0ah,0dh,"Proramme Terminated. $"
warning_msg db 0ah,0dh,"Input is not a letter. Try agian.",0ah,0dh,"$"

.code ; starting of Code segment

main proc
mov ax,@data ; copying starting address of data segment into ax register
mov ds,ax ; by copying ax into ds we are initializing data segment

lea dx,stop_msg
mov ah,9
int 21h
@input:
mov cx,0

lea dx,input_msg
mov ah,9
int 21h

mov ah,1 ; taking single input charachter
int 21h

cmp al,27d ; cheking if it input is 'esc' or not
je @terminate

call $check_constraints ; procedure calling

cmp cx,1 ; cheking flag value
je @input

xor bx,bx ; XOR with self will always retun of all zero bit (means clearing a register)
mov bl,al
xor bl,32d ; Here is the bit trick

@output:
lea dx,output_msg
mov ah,9
int 21h

mov dl,bl ; output char was stored in bl
mov ah,2
int 21h

lea dx,n_line ; new line for next input
mov ah,9
int 21h

jmp @input

@terminate:
lea dx,end_msg
mov ah,9
int 21h

mov ah,4ch ; terminate program
int 21h
main endp ; ending of main procedure

$check_constraints proc
; if( (input<= 122d && input <= 97d) || (input<=90d && input <= 65d)) Then Proceed; otherwise Warning;
@first_if:
cmp al,122d ; or cmp al,'z'
jg @warning

cmp al,97d ; or cmp al,'a'
jge @setFlag

@second_if:
cmp al,90d ; or cmp al,'Z'
jg @warning

cmp al,65d ; or cmp al,'A'
jl @warning

@setFlag:
mov cx,0 ; i'm considering cx register as a flag
jmp @end_function

@warning:
mov cx,1 ; i'm considering cx register as a flag

lea dx,warning_msg
mov ah,9
int 21h

@end_function:
ret
$check_constraints endp

end main ; ending of code segment

Combining two MIPS programs to convert lowercase to uppercase and vice versa

addi $t0, $t0, -32 is faulty.

It should be addi $t1, $t1, -32 .

.data
string: .asciiz "\nThis Is A Test\n"
newline: .asciiz "\n"

.text
main:
la $t0, string # $t0 is pointer to first el of str, loading string
li $v0, 4 # print the original string
la $a0, string
syscall

li $s2, ' '
li $v0, 4
li $t0, 0

loop:
lb $t1, string($t0)
beq $t1, 0, exit
beq $t1, $s2, neither

j caseLower

caseLower:
blt $t1, 'A', caseUpper
bgt $t1, 'Z', caseUpper
addi $t1, $t1, 32
sb $t1, string($t0)
addi $t0, $t0, 1
j loop


caseUpper:
blt $t1, 'a', neither
bgt $t1, 'z', neither
addi $t1, $t1, -32
sb $t1, string($t0)
addi $t0, $t0, 1
j loop

neither:
addi $t0, $t0, 1
j loop

exit:
li $t0, 4
la $a0, string
syscall

li $v0, 10
syscall

Transform uppercase letters to lowercase and vice-versa using single parameter function (C++)

Don't reinvent the wheel. The standard library has functions to identify uppercase and lowercase letter, and to change case. Use them.

char trans(char ch) {
unsigned char uch = ch; // unfortunately, character classification function require unsigned char
if (std::isupper(uch))
return std::tolower(uch);
else
return std::toupper(uch);
}

You might be inclined to change that else branch to else if (std::islower(uch) return std::toupper(uch); else return uch;, but that's not necessary; std::toupper only changes lowercase letters to uppercase, so it won't affect characters that aren't lowercase.

Then, when you call it, just copy the result:

int i = 0;
for ( ; i < strlen(s); ++i)
s2[i] = tran(s[i]);
s2[i] = '\0';

EDIT:

Since there seems to be a requirement to do things the hard way, let's change trans to match:

void trans(char& ch) {
unsigned char uch = ch; // unfortunately, character classification function require unsigned char
if (std::isupper(uch))
ch = std::tolower(uch);
else
ch = std::toupper(uch);
}

And now, you can just apply it in place:

for (int i = 0; i < strlen(s); ++i)
trans(s[i]);

I called this "the hard way" because with the original version of trans you can use it directly to modify the original string:

for (int i = 0; i < strlen(s); ++i)
s[i] = trans(s[i]);

and you can use it to copy the string:

for (int i = 0; i < strlen(s); ++i)
s2[i] = trans(s[i]);
// don't forget the terminating nul

With pass by reference, you can only modify in place; copying requires an additional step:

strcpy(s2, s1);
for (int i = 0; i < strlen(s); ++i)
trans(s2[i]);

C++, most efficient way to change uppercase to lowercase and vice versa without condition branching

If your characters are using the ASCII character set you can xor with the value 32 to flip between upper and lower case.

char switchCase(char letter)
{
return letter ^ 32;
}


Related Topics



Leave a reply



Submit