1

Can anyone help me with assembly !? I know how to count letters, small or large one, but i cannot do both at once. Below is my code for counting small letters

  mov   bx, offset buff
  mov   cl, [bx - 1]   ;size of string
  mov   dx, 0         ;reset dx
cykluss:   
  mov   al, [bx]   ;reading all characters
  inc bx         ;increasing char in string
  cmp al,'$'  ; end of line?
  je supp 
  cmp al,'a'
  JL cykluss  ; if char < 'a' then go to the start(cykluss)
  CMP al,'z'
  JG cykluss ; if char > 'z' then go to the start(cykluss)
  inc dx      
  jmp cykluss      

supp:
  mov bx,dx
  charp 10    ;macro for new line
  CALL DISP   ;convert from dx to number

please help me thank you very much

Tiestik
  • 61
  • 1
  • 2
  • 6

2 Answers2

1

Just copy-paste and run.

To check lowercase and uppercase letters, you have to check if the character is between the extreme letters : 'A' and 'z', if so, check if the character is greater or equal than 'a', if so, it's lowercase letter, or, check if the character is less or equal than 'Z', if so, it's an uppercase letter. Get the idea? Next is your code with some changes to make it run in EMU8086 :

.stack 100h
.data

buff db 'aB[C*E-G^h#$'

lower_counter dw 0 ;COUNTER FOR LOWERCASE LETTERS.
upper_counter dw 0 ;COUNTER FOR UPPERCASE LETTERS.

msj1 db 13,10,'lowercase letters : $'
msj2 db 13,10,'uppercase letters : $'

str db 6 dup('$') ;STRING TO STORE NUMBER. 

.code          
;INITIALIZE DATA SEGMENT.
  mov  ax,@data
  mov  ds,ax

  mov   bx, offset buff    
cykluss:   
  mov al, [bx]   ;reading all characters
  inc bx           ;increasing char in string
  cmp al,'$'       ; end of line?
  je supp 

;---CHECK LETTERS ON THE EXTREMES ('A','z').

  cmp al,'A'  ; if char < 'A' then IT'S NOT A LETTER.
  JL cykluss
  cmp al,'z'  ; if char > 'z' then IT'S NOT A LETTER.
  JG cykluss  ; if char > 'z' then go to the start(cykluss)

;---CHECK LETTERS IN THE MIDDLE ('Z','a').  
;---REMEMBER : IF NEXT LINES ARE EXECUTED, IT MEANS "AL"
;---HOLDS A VALUE BETWEEN 'A' AND 'z' (65..122).                                                        

  cmp al,'a'
  JGE its_lowercase ; if char >= 'a' then IT'S A LOWERCASE LETTER.
  CMP al,'Z'
  JLE its_uppercase ; if char =< 'Z' then IT'S AN UPPERCASE LETTER.
  jmp cykluss      ; if (char > 'Z') and (char < 'a') then IT'S NOT A LETTER.

its_lowercase:  
  inc lower_counter
  jmp cykluss
its_uppercase:  
  inc upper_counter
  jmp cykluss                              

supp:
;DISPLAY TOTAL LOWERCASE.
  mov ah, 9
  mov dx, offset msj1
  int 21h

  call dollars
  mov ax, lower_counter ;PARAMETER FOR NUMBER2STRING.
  call number2string ;RESULT RETURNS IN "STR".

  mov ah, 9
  mov dx, offset str
  int 21h

;DISPLAY TOTAL UPPERCASE.
  mov ah, 9
  mov dx, offset msj2
  int 21h

  call dollars
  mov ax, upper_counter ;PARAMETER FOR NUMBER2STRING.
  call number2string ;RESULT RETURNS IN "STR".

  mov ah, 9
  mov dx, offset str
  int 21h

;FINISH THE PROGRAM.
  mov  ax,4c00h
  int  21h           

;------------------------------------------

;NUMBER TO CONVERT MUST ENTER IN AX.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING.

proc number2string
  mov  bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:       
  mov  dx, 0 ;NECESSARY TO DIVIDE BY BX.
  div  bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
  push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
  inc  cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
  cmp  ax, 0  ;IF NUMBER IS
  jne  cycle1 ;NOT ZERO, LOOP. 
;NOW RETRIEVE PUSHED DIGITS.
  mov  si, offset str
cycle2:  
  pop  dx        
  add  dl, 48 ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl
  inc  si
  loop cycle2  

  ret
endp  

;------------------------------------------
;FILLS VARIABLE STR WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THESE STRINGS WILL BE DISPLAYED.
proc dollars                 
  mov  si, offset str
  mov  cx, 6
six_dollars:      
  mov  al, '$'
  mov  [ si ], al
  inc  si
  loop six_dollars
  ret
endp  

What we need to do is to check if AL is between two numeric ranges :

enter image description here

  • Can I ask something? I m reading all chars to the end($) but what if i have somewhere in string character $. It will read only to the first $. How can i avoid that ? or fix it ? thanks – Tiestik Apr 14 '15 at 14:40
  • Two options : use another character that user cannot input, like chr(0), or, use string length. – Jose Manuel Abarca Rodríguez Apr 14 '15 at 14:41
  • 1. I cannot use string lenght. 2. can u explain me more about the first option - chr(0) or show me. I edited a post below to show u how it looks like. – Tiestik Apr 14 '15 at 14:57
  • It's simple : current buff is DB 'aX#-Uv!$', let's end it with zero : DB 'aX#-Uv!',0 . Notice the zero is OUTSIDE the single quotes (after a comma), if zero would be INSIDE, it wouldn't be 0, it would be '0' (ASCII 48). Now you can use CMP AL,0 (not CMP AL, '0'). – Jose Manuel Abarca Rodríguez Apr 14 '15 at 15:01
  • yes this is a simple but I have more complicated program than this. I load a string(name of file). If the string is equal to the name of file then I can open the file and read from that file. And then strating my problem again with $ – Tiestik Apr 14 '15 at 15:18
  • To read from a file, it's necessary to tell the interrupt how many characters we want to read, and, after the interrupt executes, it returns in AX how many characters were read. That's the length we can use. You can read in blocks of, let's say, 50 characters, and count letters until you reach the length in AX, not until '$' or zero. – Jose Manuel Abarca Rodríguez Apr 14 '15 at 15:21
  • ok i try to look in this. I edited a post below that u could imagine how my code looks like – Tiestik Apr 14 '15 at 15:26
  • Can you give me some contact on you (email, fb etc.) because I can't send you a message( low reputation ). I could use your advices on other program in assembly. :) thanks – Tiestik Apr 20 '15 at 10:47
  • I could, but by email I wouldn't make any points :) So, let's keep it here, in stackoverflow. Anytime you need help, just post a question and you will get the answer in a few minutes. – Jose Manuel Abarca Rodríguez Apr 20 '15 at 14:56
  • if you could look at this :) https://stackoverflow.com/questions/29819483/assembly-how-to-do-sum-between-two-numbersinterval – Tiestik Apr 23 '15 at 09:48
1

Nice going. You actually tried to solve the problem on your own first. Not only that, but you put in good comments in your source code.

Here is my 6 minute makeover for your original attempts. I've tried to leave your labels intact. Do note that the comments include some white space so that they line up on the page way more neatly. You'll find that you get a thousand times more respect based on neat looking code. You'll find this almost worldwide.

Oh, big disclaimer: I didn't run this, so, please see if it works on your side with your debugger and so on.

One thing to notice: I used JA and JB instead of your JG and JL. If you're not aware of why this is important here, post a comment and I'll go into more detail.

Hope this helps; happily offered, yours free, with money back guarantee...

   Mov   bx, offset buff
   Mov   cl, [bx - 1]               ;size of string
   Mov   dx, 0                      ;Dx will hold UPPERcase count
   Mov   cx, 0                      ;Cx will hold lowercase count

 cykluss:   

   Mov      al, [bx]                ;reading all characters
   Inc      bx                      ;increasing char in string

   Cmp      al,'$'                  ;end of line?
   Je       supp                    ;yes



                                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                    ;;  Check for the byte between 'a' and 'z' ;;
                                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   Cmp      al,'a'                  ;Is it below lower case 'a' ?
   JB       Not_Lower_Case          ;Yes, so it's not lower case

   CMP      al,'z'                  ;Is it above lower case 'z' ?
   JA       Not_Lower_Case          ;Yes, so it's not lower case

   Inc      Cx                      ;Else, the byte is between 'a' and 'z' so count it
   Jmp      cykluss                 ;Go do the next char



                                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                    ;;  Now, same thing for capital 'A' and 'Z';;
                                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 Not_Lower_Case:

   Cmp      al,'A'                  ;Is it below upper case 'A' ?
   JB       Not_Upper_Case          ;Yes, so it's not lower case

   CMP      al,'Z'                  ;Is it above upper case 'Z' ?
   JA       Not_Upper_Case          ;Yes, so it's not lower case

   Inc      Dx                      ;Else, the byte is between 'A' and 'Z' so count it and drop through

 Not_Upper_Case:                    ;If we hit this label, it was neither upper nor lower

   Jmp      cykluss                 ;Go do the next char


                                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                    ;;  Note to original poster, you now have  ;;
                                    ;;  two counters, one in Cx and the other  ;;
                                    ;;  in Dx such as you had in your attempt  ;;
                                    ;;  when you started. It is now up to you  ;;
                                    ;;  to put it into your macro to make the  ;;
                                    ;;  output work for both numbers instead.  ;;
                                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


 supp:

   Mov bx,dx

   Charp 10                         ;macro for new line

   CALL DISP                        ;convert from dx to number
User.1
  • 2,562
  • 3
  • 33
  • 40
  • 1
    y thanks for your time i didnt notice your post, because i was busy writing mine :) it helps as well, but can u show me how to convert cx to number ? thanks – Tiestik Apr 13 '15 at 17:37
  • see if this works: `Mov bx,cx` then do your `Charp` and your `CALL DISP` – User.1 Apr 13 '15 at 17:55
  • y thats working but when i want convert both of them(cx and dx) to number for some reason it working only for first one: mov bx,cx,charp 10,CALL DISP then mov bx, 0 (reset bx )and then second convert mov bx,dx,charp 10,CALL DISP – Tiestik Apr 13 '15 at 18:01
  • 1
    This is beyond your original question. You'll need to search for the way to convert a binary number (which is in a regirster) to ascii and output it. – User.1 Apr 13 '15 at 18:11