Hello, I've been working on this code for a while and I can't get it to display A to a(Uppercase to lowercase) as well as lower to upper, a to A. I've looked around and found suggestions on here and googel from other similar threads that I've tried but none have helped. Help please. Commented out at line 51 is what I was trying before

EDIT: USING EMU 8086. Intel x86

org 100h

jmp start

string db 20, 22 dup('?')
revstring db 20, 22 dup('?') 
size dw 4 

new_line db 0Dh,0Ah, '$' 


lea dx, string

mov ah, 0ah
int 21h 

mov bx, dx
mov ah, 0
mov al, ds:[bx+1]
add bx, ax 

mov byte ptr [bx+2], '$' 

lea dx, new_line
mov ah, 09h
int 21h

lea bx, string

mov ch, 0
mov cl, [bx+1] 
mov size, cx 

jcxz null 
add bx, 2 


cmp byte ptr [bx], 'a'- 'A'   
;;OR cmp byte ptr [bx], 'A' + 32
jb ok           

and byte ptr [bx], 11011111b ;


mov ah, byte ptr [bx]
push ax

inc bx 
loop upper_case

mov cx, size

lea bx, revstring

pop ax
mov byte ptr [bx], ah
inc bx 
loop reverse

mov byte ptr [bx],'$' 

lea dx, revstring
mov ah, 09h
int 21h

mov ah, 0
int 16h


The difference between upper and lower case in ASCII characters is bit 5.

"D" = 44H = 0100 0100
"d" = 64H = 0110 0100

So striping bit 5 converts to upper and setting bit 5 converts to lower

    mov     al, 64H            ; AL = "d"
    and     al, 5FH            ; AL = "D"
     or     al, 20H            ; AL = "d"
    xor     al, 20H            ; AL = "D"

Each time you exclusive or the value it toggles from lower to upper, or upper to lower

why can i not just add 32 or take away 32 to get the upper/lower case equivalent?

why wont something like this work?

cmp byte ptr [bx], 'a' XOR 'a' - 20h
jb ok

cmp byte ptr [bx], 'z' XOR 'z' - 20h
ja ok
cmp byte ptr [bx], 'A' XOR 'A' + 20h
jb ok              

cmp byte ptr [bx], 'Z' XOR 'Z' + 20h
ja ok

Your logic is sound, but the problem is it could make your app crash. Your algo assumes operator will not make any mistakes or there aren't any inconsistencies in a data file. Image if you have "d" 64H and you add 20H to it. The result is 84H which would probably be unprintable character or something else depending on the character set.

Masking bits will at least give you the correct letter, but maybe not the case you were expecting

ShiftLeft already answered why adding or subtracting 32 won't work. However, also consider this: Control characters and other non-alphabetic characters have no upper/lower case equivalence. toggling bit 5 on these characters will produce very strage results indeed. A lower case "space" character is a null - it terminates the string. How do you interpret upper case carriage returns or linefeeds? The only safe technique is to load each character, remove bit 5 and test to make sure the result is between 'A' and 'Z'. Only then can you xor bit 5. Perhaps something like this:

    mov cx,n        //n is length of string
    push es         //save old es
    mov es,ds       //stosb must use es but lodsb uses ds
    cld             //Set pointers to increment
    mov si,string1  //Load source pointer
    mov di,string2  //load dest pointer
    lodsb           //Get byte to al from string1 and incr. si
    mov ah,al       //save a copy
    and al,0xDF     //remove bit 5 (0xDF is complement of 0x20)
    cmp al,'A'
    jb notAlpha     //not alpha if LT 'A'
    cmp al,'Z'
    ja notAlpha     //not alpha if GT 'Z'
    xor ah,' '      //toggle saved copy's case
    mov al,ah       //Get back saved character
    stosb           //save the byte to string2 and incr di
    loop LoopHere   //Loop till count 0
    pop es          //restore old es

Saving/restoring other registers may be needed as well.

OOPS: Forgot OFFSET operators when loading pointers. Lines 5 and 6 should be

mov si,offset string1 //Load source pointer
mov di,offset string2 //load dest pointer