News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

upper case to lower case

Started by scooter4483, March 02, 2006, 09:26:36 PM

Previous topic - Next topic

scooter4483

i searched the site and found some but not a lot of similar questions to mine.  Here is some of my code, it converts from lower case to upper case, but my a2 is not converting my lower case to upper case.  did i miswrite something.

Main PROC
    call ClrScr                    ;clears the screen
    mov edx, OFFSET String1       
    call WriteString               ;displays String1
    call Crlf                      ;carriage return line feed

    mov ecx, 99            ;the max # of char. stored in memory
    mov edx, OFFSET String3
    call ReadString         ;eax returns # of Char. read 
    call Crlf                      ;carriage return line feed
    call Crlf                      ;carriage return line feed

    mov edx, OFFSET String2
    call WriteString
    call Crlf
   
    mov edx, OFFSET String3

A0: mov al, [edx]       
    cmp al, 0           
    je Display_String
    cmp al, 'A'      ;from here it will convert from lower to uppercase
    jb A2
    cmp al, 'Z'
    ja A2
    add al, 'a'-'A'
    mov [edx], al

A2: cmp al, 'a'      ;A2 will change from uppercase to lowercase
    jb A1
    cmp al, 'z'
    ja A1
    add al, 'A'-'a'
    mov [edx], al

A1: inc edx
    jmp A0

Display_String: mov edx, OFFSET String3
      call WriteString
      call Crlf
      call Crlf
        exit

Main ENDP

scooter4483

never mind.  all i needed was conveting the uppercase to lower case.  This is how i did it:

INCLUDE Irvine32.inc

.data

    String1 BYTE "Enter a string: ", 0
    String2 BYTE "Here is the processed result: ", 0
    String3 BYTE 100 dup(?)

;---------------------------------------------------
.code


Main PROC
    call ClrScr                                  ;clears the screen
    mov edx, OFFSET String1       
    call WriteString                          ;displays String1
    call Crlf                                     ;carriage return line feed

    mov ecx, 99                      ;the max # of char. stored in memory
    mov edx, OFFSET String3
    call ReadString         ;eax returns # of Char. read 
    call Crlf                                      ;carriage return line feed
    call Crlf                                      ;carriage return line feed

    mov edx, OFFSET String2
    call WriteString
    call Crlf
   
    mov edx, OFFSET String3

A0: mov al, [edx]       
    cmp al, 0           
    je Display_String
    cmp al, 'A'         ;upper to lower
    jb A1
    cmp al, 'Z'
    ja A1
    add al, 'a'-'A'
    mov [edx], al

A1: inc edx
    jmp A0

Display_String: mov edx, OFFSET String3
      call WriteString
      call Crlf
      call Crlf
        exit

Main ENDP

HERE IS MY NEXT QUESTION.  How do I read each letter from the user input so that it replaces the letter with 3 letters ahead.  For example,  if the user put in Hello, the result would be "khoor".  what is did was take the h and replaced it with h+3 which is k, and so on.  Thanks guys.

Mark Jones

Hi scooter. Changing bytes is very easy once you get the hang of it. Here's some commented snippets to get you thinking:


    mov ecx,offset szMyString                      ; ecx = offset of MyString
    mov al,byte ptr [ecx]                          ; get new byte at offset ecx into al
    inc ecx                                        ; point to next byte of szMyString
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

scooter4483

thanks for the response, but i'm a little confused.  i cant relate that to moving the letters ahead by 3.  Is there any other hints or something?  thanks.

PBrennick

    mov ecx,offset szMyString                      ; ecx = offset of MyString
    mov al,byte ptr [ecx]                          ; get new byte at offset ecx into al
    add  al,3                                      ; bump it up 3 places
    mov byte ptr [ecx], al                         ; put it back
    inc ecx                                        ; point to next byte of szMyString


You might want to test the value in al to make sure it is a letter and has a value less than 'w' but that is up to you, the code will work.  Don't forget to handle uppercase, maybe convert all uppercase letters to lower.

By the way, how do you plan to handle x,y and z?  Wrap around to a,b and c?  if so, if al is a letter greater than 'w' then instead of adding 3, subtract 23.

Sorry, several edits here as things occurred to me, have fun.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

scooter4483

where does this code go?  is it directly after my A0 like this

A0: mov al, [edx]       
    cmp al, 0           
    je Display_String
    cmp al, 'A'                  ;upper to lower
    jb A1
    cmp al, 'Z'
    ja A1
    add al, 'a'-'A'
    mov [edx], al

    mov ecx,offset szMyString                      ; ecx = offset of MyString
    mov al,byte ptr [ecx]                          ; get new byte at offset ecx into al
    add  al,3                                      ; bump it up 3 places
    mov byte ptr [ecx], al                         ; put it back
    inc ecx                                        ; point to next byte of szMyString



scooter4483

in the code szMystring, should I make it:

Mystring BYTE "abcd...z"

scooter4483

im more confused now than before.  Do I have to compare again or something as well?  Man, am i stressing right now.  :(

scooter4483

So I did this:

A0: mov al, [edx]       
    cmp al, 0           
    je Display_String
    cmp al, 'A'                  ;upper to lower
    jb A1
    cmp al, 'Z'
    ja A1
    add al, 'a'-'A'
    mov [edx], al

    mov edx, OFFSET String3
    mov al, byte ptr [edx]
    sub al, 23
    mov byte ptr [edx], al
    inc edx

and im getting some weird answers:  When I input  'A' it returns 'J'.  It should make the letter lowercase and should return D.  What gives?  Thanks again and sorry for all my fuss.

Mark Jones

Quote from: scooter4483 on March 03, 2006, 07:05:46 AM
    mov edx, OFFSET String3
    mov al, byte ptr [edx]
    sub al, 23
    mov byte ptr [edx], al
    inc edx

... When I input  'A' it returns 'J'...

Hi Scooter, try not to stress, you're almost there.
Do you need case altering? If so, first make sure that it is working properly, THEN tackle the letter altering. Working with multiple unknowns is always much more difficult than working with one unknown. Simplify. :)
Here's some useful info.

41h-5Ah = uppercase letters.
61h-7Ah = lowercase letter. To convert upper to lower, add 20h (32d). To convert lower to upper, subtract 32.

Here's the routine I use in my Lib Search Tool to change case, somewhat simplified. Perhaps you can learn from it.


@@:                              ; this is an "anonymous jump label"
    mov al,byte ptr [ecx]        ; get byte from pointer ecx into al
    inc ecx                      ; point to next byte
    cmp al,"A"                   ; is our byte less than 41h?
    jl @F                        ; if so, skip that...
    cmp al,"z"                   ; or more than 7Ah?
    jg @F                        ; if so, don't change those either...
    cmp al,"Z"                   ; if it's less than 5Ah, convert to upper
    jle convupper
    cmp al,"a"                   ; if it's greater than 61h, convert to lower
    jge convlower
    jmp @F                       ; else jump out, not a letter
convlower:   
    sub al,32                    ; byte is converted to lowercase now
    jmp @F
convupper:
    add al,32                    ; byte is converted to upper
@@:                              ; case of byte in al is now reverse (but only if alphabetic!)


There are some interesting string examples in \masm32\help\ASMINTRO.HLP under "Working with Strings" and it covers exactly this. You are so very close to solving this by yourself Scooter, won't you try it tomorrow?
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

ChrisLeslie

This should convert to lowercase using high level syntax.

; #########################################################################

      .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

; #########################################################################

      include \masm32\include\windows.inc
      include \masm32\include\masm32.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
     
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
     
      include \masm32\macros\macros.asm
   
      Main   PROTO

; #########################################################################

    .data
      Msg1        db "Type something: ",0
      Msg2        db "As lowercase: ",0
      Buff        db 80 dup(0)
      BuffUpper   db 80 dup(0),13,10,0

; #########################################################################

    .code

    start:
      invoke Main
      invoke ExitProcess,0

; #########################################################################

Main proc

    invoke StdOut,SADD("Upper/lower case test",13,10,13,10)
    invoke StdOut,ADDR Msg1
    invoke StdIn,ADDR Buff,LENGTHOF Buff
    invoke StdOut,ADDR Msg2
    mov esi,offset Buff
    mov edi,offset BuffUpper
    ;***********************
    .while(eax != 13)   
      lodsb
      .if(eax!=13)
        or eax,20h          ; this part does the conversion
      .endif
      stosb
    .endw
    ;***********************
    invoke StdOut,ADDR BuffUpper
    invoke StdOut,SADD(13,10)
    invoke StdOut,SADD("Press enter...")
    invoke StdIn,ADDR Buff,LENGTHOF Buff
   
    ret

Main endp

; #########################################################################

    end start


Hope that helps

Chris

Vortex

Scooter,

The masm32 packages comes with string handling functions like lcase and ucase , you should try them.

donkey

I use the incredibly inefficient table method, never timed it but I have always assumed that because there are no jumps or condition tests (except for the end of string) that it is faster, probably way off base though.

// Translation matrix for lower case conversion - 256 bytes
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


lea ebx,lcase
mov edi, [pString]
xor eax,eax
:
mov al, [edi]
xlatb
mov B[edi],al
add edi,1
or al, al
jnz <
ret
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

scooter4483

thanks for the responses.  the code works, meaning it converts to lowercase if i take out the following code:

   mov ecx,offset szMyString                      ; ecx = offset of MyString
    mov al,byte ptr [ecx]                           ; get new byte at offset ecx into al
    sub al, 23                                            ; bump it up 3 places
    mov byte ptr [ecx], al                          ; put it back
    inc ecx                                               ; point to next byte of szMyString

but the code above im trying to use to figure out how to take the letters and move them over by 3.  is the syntax not matching up with the rest of my code or something?

PBrennick

scooter4483,
You need to replace sub al, 23 with add al, 3

Somehow, I must have confused you.  sub al, 23 is ONLY if al  is a lower case letter greater than 'w'

Do you understand this?  Let us resume with that question.  Any of us could give you a complete working example but this is a perfect learning experience for you.  You need to work on each of the most recent suggestions you get from any of us, try to go further and then ask us your next question if one comes up.  There is no need to get stressed out, everone here really wants to help you.  Stay calm and try to enjoy the moment, it will never come again because once you learn it, it isn't as much fun any more.  This is 'your' time.

Paul
The GeneSys Project is available from:
The Repository or My crappy website