0

In assembly, lower case to upper case or upper case to lower case conversion is easy. if input is lower case then adding 32d will give the upper case letter Or if input is upper case, then subtracting 32d will give lower case letter. But I want to do this conversion without using subtraction or addition.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • We already have Q&As for the ASCII trick, and for doing it in x86 asm. Wrapping a DOS program around it that reads 1 char at a time and prints messages is probably more useful as an example of using DOS calls to read / modify / print a character than of that specific ASCII trick. – Peter Cordes Jun 02 '21 at 08:28

1 Answers1

0

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
  • 1
    `xor bx,bx` seems pointless; you're not using BH or the full BX in any later instruction. See also [What is the idea behind ^= 32, that converts lowercase letters to upper and vice versa?](https://stackoverflow.com/a/54585515) and [How to access a char array and change lower case letters to upper case, and vice versa](https://stackoverflow.com/a/35936844) for a more efficient way to check if a character is alphabetic (upper or lower case). (Just `or al, 0x20` / `sub al, 'a'` / `cmp al, 'z'-'a'` / `ja non_alpha`, instead of four cmp/jcc pairs.) – Peter Cordes Jun 02 '21 at 08:05