Search code examples
stringassemblydosx86-16

Lowercase to Uppercase program not capitalizing when it should


I am writing an assembly program that capitalizes the first letter of each word in the sentence I input.

My problem is that it doesn't capitalize the first letter of the words. What's wrong with my code?

Below is my code

.model small
.stack 100h
.data
    prompt1 db "Input String: $"
    prompt2 db "Output String: $"
    InputString db 21,?,21 dup("$")  
    newline db 10,13,"$"
.code
start:
    mov ax, @data
    mov ds, ax

    ; Getting input string
    mov ah,09h
    lea dx, prompt1
    int 21h

    lea si, InputString
    mov ah, 0Ah
    mov dx, si
    int 21h

nextline: 
    mov ah, 09h
    lea dx, newline
    int 21h

loop1:   
    mov cl, [si+1]
    mov ch,0
    add si, cx
    inc si 
    dec cx
    cmp cx, 0
    je exit
    jmp checkspace

checkspace:
    cmp si, " "
    inc si
    je checkletter

checkletter:
    cmp si, "a"
    jae checkletter2

    checkletter2:
    cmp si, "z"
    jbe capital

capital:
    mov ah, [si]
    xor ah, 00100000b
    mov [si], ah
    jmp loop1  

exit:    
    mov ah,09h
    lea dx, prompt2
    int 21h

    mov ah, 09h
    mov dx, offset InputString+2
    int 21h   

    mov ah, 4ch
    int 21h
end start

Below is the updated part of my code. It can now only capitalize the first letter of the word. I don't know if the problem is with the loop. Please help me figure out which part of my code is wrong. I'm so sorry I don't know how to use a debugger for checking. Thank you.

    mov cl, [si+1]
    mov ch,0
    add si,2
    jmp checkletter

loop1:
    inc si
    dec cx
    cmp cx, 0
    je exit
    cmp si, " "
    je checkletter3
    jmp loop1

checkletter:
    cmp si, 41h
    jae checkletter2

checkletter2:
    cmp si, 5Ah
    jbe capital

checkletter3:
    inc si
    dec cx
    jmp checkletter

capital:
    mov ah, [si]
    xor ah, 00100000b
    mov [si], ah
    jmp loop1

Solution

  • cmp si, " "  
    cmp si, "a"
    cmp si, "z"
    cmp si, 41h
    cmp si, 5Ah
    

    All of the above are comparing the address in SI with an immediate value. They are not comparing the byte that can be found at the address that SI is pointing to with the immediate! You need to dereference it.

    cmp byte [si], " "
    cmp byte [si], "a"
    cmp byte [si], "z"
    cmp byte [si], 41h
    cmp byte [si], 5Ah
    

    To solve the task of capitalizing just the first letter of each word

    • You first need to find the start of each word. This is done by skipping the whitespace in front of each word.
    • Once located, you compare to see if the starting character is in small caps, and only if it is, you convert it to uppercase by subtracting 32.
    • The rest of the word is again skipped until either the end of the line is encountered or another whitespace is found for which the process starts all over again from the top.

    It look like this:

     mov  cl, [si+1]  
     test cl, cl           ;Exit if the input was empty!!!  
     jz   Exit  
     add  si, 2            ;Point at first byte  
    
    SkipSpace:  
     mov  al, [si]  
     cmp  al, " "  
     jne  FirstCharacter  
     inc  si               ;(*)
     dec  cl
     jz   Exit
     jmp  SkipSpace
    
    FirstCharacter:
     cmp  al, "a"
     jb   SkipRemainingCharacters
     cmp  al, "z"
     ja   SkipRemainingCharacters
     sub  al, 32           ;Capitalize
     mov  [si], al         ; and write back in string
    
    SkipRemainingCharacters:
     inc  si
     dec  cl
     jz   Exit
     mov  al, [si]
     cmp  al, " "          ;If not space then it's part of same word
     jne  SkipRemainingCharacters
     jmp  SkipSpace        ;This could just as easily jump to (*)
    
    Exit: