The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: Pro32 on February 19, 2005, 11:53:17 PM

Title: Changing to Lower case
Post by: Pro32 on February 19, 2005, 11:53:17 PM
I been having trouble. I want to change my sentence to lower case except for the first letter in each word. I been told to campare it to a space (20h) but I don't know how to do it. Help anyone?? Thanks in advance.


.data

sentence BYTE "CHANGE TO LOWER CASE!!"
sentence1 BYTE 30 DUP (?)

.code
main PROC
   ;this prints the original sentence
   mov edx, OFFSET sentence
   call WriteString
   call Crlf


   ;Print sentence in  Lowercase letters
   mov ecx, LENGTHOF sentence1
   mov esi, 0
   mov al,0      

L1:
   mov al, sentence[esi]
   cmp esi,0
   je NoUpperCase ;for the first symbol
   cmp al,41h
   jl NoUpperCase ; if less then 'A'
   cmp al,5ah
   jg NoUpperCase  ;if greater then 'Z'
   add al,32d


NoUpperCase:
   mov sentence[esi], al
   inc esi
   ;mov edx, OFFSET sentence   
   loop L1
      

   call WriteString
   call Crlf

   exit
main ENDP
END main
Title: Re: Changing to Lower case
Post by: MichaelW on February 20, 2005, 01:07:03 AM
To determine if the character is above 'Z', compare it to the character code for 'Z':

cmp al,'Z'
ja  NoUpperCase


Title: Re: Changing to Lower case
Post by: pbrennick on February 20, 2005, 02:15:38 AM
Pro32,
Here is a procedure that is flag driven:

If flag = 3 then invert case, if upper convert selected text to lower or if lower convert selected text to upper.
If flag = 2 then convert selected text to upper.
If flag = 1 then convert selected text to lower.

ChangeCase proc
;---------------------------------------
        inv  SendMessage, hREdit, EM_EXGETSEL, 0, offset cr   ; Get start and ending positions of highlighted text
        mov eax, cr.cpMax               ; Get end position
        sub eax, cr.cpMin               ; Minus the start position
        .if eax < 255                   ; If in range...
          inv  SendMessage, hREdit, EM_GETSELTEXT, 0, addr szFlipCase     ; Get selected text
        .endif                          ; End of conditional
        push edi                        ; Register preservation
        mov edi, Offset szFlipCase      ; Pointer to text selection storage buffer
J001:   mov al, [edi]                   ; Get a character
        .if Flag == 3                   ; Invert selected text
          .if al >= 'A' && al <= 'Z'    ; If upper case...
            or byte ptr [edi], 20h      ; Convert it to lower case
          .elseif al >= 'a' && al <= 'z'    ; If lower case...
            and byte ptr [edi], 5fh     ; Convert it to upper case
          .endif                        ; End of conditional
        .elseif Flag == 2               ; Convert selected text to upper case
          .if al >= 'a' && al <= 'z'    ; If lower case...
            and byte ptr [edi], 5fh     ; Convert it to upper case
          .endif                        ; End of conditional
        .elseif Flag == 1               ; Convert selected text to lower
          .if al >= 'A' && al <= 'Z'    ; If upper case...
            or byte ptr [edi], 20h      ; Convert it to lower case
          .endif                        ; End of conditional
        .endif                          ; End of conditional
        inc edi                         ; Update the buffer pointer
        or al, al                       ; Done?
        jne J001                        ; Continue until ASCIIZ is reached
        pop edi                         ; Restore the register
;       Put back the reconditioned text
        inv  SendMessage, hREdit, EM_REPLACESEL, TRUE, addr szFlipCase
        ret                             ; Return to caller
;---------------------------------------
ChangeCase endp


Paul
Title: Re: Changing to Lower case
Post by: donkey on February 20, 2005, 02:17:24 AM
If size is not a factor you might think about using a table and XLATB. It is fairly fast once the table is in the data cache...

align 16
lcase:
db   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
db  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
db  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
db  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
db  64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111
db 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95
db  96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111
db 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127
db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
db 144,145,146,147,148,149,150,151,152,153,154,155,156,156,158,159
db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,173,175
db 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
db 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
db 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
db 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255


lszCase FRAME pString
uses ebx,esi,edi

mov ebx,offset lcase

mov edi,[pString]
mov esi,[pString]
xor ecx,ecx
:
mov al,[esi+ecx]
xlatb
mov [edi+ecx],al
inc ecx
or al,al
jnz <
:

mov eax,edi
RET
ENDF


For upper case use the same routine but change the table...

align 16
ucase:
db   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
db  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
db  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
db  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
db  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
db  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
db  96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
db  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127
db 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
db 144,145,146,147,148,149,150,151,152,153,154,155,156,156,158,159
db 160,161,162,163,164,165,166,167,168,169,170,171,172,173,173,175
db 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
db 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
db 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
db 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
db 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
Title: Re: Changing to Lower case
Post by: pbrennick on February 20, 2005, 03:20:30 AM
Nowadays with the extreme disk sizes we get to play with, size is no longer much of an issue.  Tables are pretty fast, too, Donkey?

Paul
Title: Re: Changing to Lower case
Post by: donkey on February 20, 2005, 03:33:58 AM
I think they are a little slow generally but I would imagine that they must be faster than a large grouping of compares and jumps. I usually use the table method as in reality there is never too much data to translate, a few hundred chars at the most. I would think that the programmatic method would be faster on small strings, I have never really tested it.
Title: Re: Changing to Lower case
Post by: raymond on February 20, 2005, 04:39:00 AM
Pro32

To answer your question, add the following instructions just before you change from upper to lower case:

cmp  byte ptr[esi-1]," "  ;checks if previous character was a space
jz   NoUpperCase          ;don't change the 1st letter of a word


Raymond
Title: Re: Changing to Lower case
Post by: Randall Hyde on February 20, 2005, 05:36:20 AM
Quote from: Pro32 on February 19, 2005, 11:53:17 PM
I been having trouble. I want to change my sentence to lower case except for the first letter in each word. I been told to campare it to a space (20h) but I don't know how to do it. Help anyone?? Thanks in advance.

Actually, the more difficult problem is figuring out what is the first character of each word.  Different people have different ideas about what constitutes a "word". So you should specify that first.  After you can pick out individual words from a string, then the lower case conversion is easy.

BTW, do you *ignore* the first character of each word, or do you convert it to upper case?
Cheers,
Randy Hyde
Title: Re: Changing to Lower case
Post by: Pro32 on February 20, 2005, 03:45:57 PM
Quote from: raymond on February 20, 2005, 04:39:00 AM
Pro32

To answer your question, add the following instructions just before you change from upper to lower case:

cmp  byte ptr[esi-1]," "  ;checks if previous character was a space
jz   NoUpperCase          ;don't change the 1st letter of a word


Raymond


I've tried adding those lines but it crashes my program. Where exactly do I put it...and what goes in between the quotation marks... I think I have an idea of where your going so this helps a lot. Thanks
Title: Re: Changing to Lower case
Post by: Pro32 on February 20, 2005, 03:47:20 PM
Quote from: Randall Hyde on February 20, 2005, 05:36:20 AM
Quote from: Pro32 on February 19, 2005, 11:53:17 PM
I been having trouble. I want to change my sentence to lower case except for the first letter in each word. I been told to campare it to a space (20h) but I don't know how to do it. Help anyone?? Thanks in advance.

Actually, the more difficult problem is figuring out what is the first character of each word.  Different people have different ideas about what constitutes a "word". So you should specify that first.  After you can pick out individual words from a string, then the lower case conversion is easy.

BTW, do you *ignore* the first character of each word, or do you convert it to upper case?
Cheers,
Randy Hyde


I want to ignore it because its already in Upper Case.
Title: Re: Changing to Lower case
Post by: raymond on February 20, 2005, 05:36:44 PM
QuoteI've tried adding those lines but it crashes my program. Where exactly do I put it...and what goes in between the quotation marks... I think I have an idea of where your going so this helps a lot. Thanks

You can use characters between quotation marks and they will be interpreted by the assembler as their ASCII code. MichaelW provided you with an example:
cmp al,"Z" is the same as cmp al,5ah.
And " " is the same as using 20h.

Using such technique makes the code easier to visualize and you don't need to refer to an ASCII conversion table for all the characters.

If you have not changed the code you originally posted, the instructions I suggested would go immediately before the add al,32d. And I can't see why the program should crash unless you did change that original code.

Raymond

P.S. You should also start practicing the use of null-terminated strings. Those are a necessity if you intend to use a lot of the Windows API functions. It's also a lot easier to detect the end of a string instead of relying on the count of characters returned by LENGTHOF and then using either a register or memory to keep track of it.
Title: Re: Changing to Lower case
Post by: Pro32 on February 20, 2005, 08:20:07 PM
Quote from: raymond on February 20, 2005, 05:36:44 PM
QuoteI've tried adding those lines but it crashes my program. Where exactly do I put it...and what goes in between the quotation marks... I think I have an idea of where your going so this helps a lot. Thanks

You can use characters between quotation marks and they will be interpreted by the assembler as their ASCII code. MichaelW provided you with an example:
cmp al,"Z" is the same as cmp al,5ah.
And " " is the same as using 20h.

Using such technique makes the code easier to visualize and you don't need to refer to an ASCII conversion table for all the characters.

If you have not changed the code you originally posted, the instructions I suggested would go immediately before the add al,32d. And I can't see why the program should crash unless you did change that original code.

Raymond

P.S. You should also start practicing the use of null-terminated strings. Those are a necessity if you intend to use a lot of the Windows API functions. It's also a lot easier to detect the end of a string instead of relying on the count of characters returned by LENGTHOF and then using either a register or memory to keep track of it.


It works! I just had to tweek your code a bit.  I'm using registry to store characters because I'm new to this language. I hope I'll get better with the help of this community. Thanks a bunch.