0

Hey guys can you help? I dont know how to do sum between two numbers For example :

first number>1

second number>5

sum would be > 1+2+3+4+5 = 15

I did only sum of two numbers. I dont know how to do this number sequences, my code is below. Thank you

MAIN:
    MOV AX, SEG DATA
    MOV DS,AX

    mov ah, 9h                  ; msg for first number
    lea dx, msg
    int 21H

    mov ah, 1h                  ; read char
    int 21H

    sub al, '0'                 ; strip ASCII
    mov x, al                   ; storing first number

    mov ah, 9h                  ; msg for second number
    lea dx, msg2
    int 21H

    mov ah, 1h                  ; read char
    int 21H

    sub al, '0'
    mov y, al                   ; storing second number

    mov ah, 9h                  ; msg for sum
    lea dx, msg3
    int 21H

    mov dl, x
    add dl, y
    add dl, '0'                 ; x + y

    mov ah, 2h                  ; printing
    int 21H


    MOV AX,4C00H    ;end
    INT 21H

CODE ENDS
    END MAIN
Tiestik
  • 61
  • 1
  • 2
  • 6
  • Not only did you not add what you tried (this really hardly counts), but your current code is flawed in that it will only work with a sum that does not exceed 9. – Jongware Apr 23 '15 at 12:26

4 Answers4

1

Here's the pseudo-code (up to you to translate to assembly):

count = firstNumber
endCount = secondNumber + 1
total = 0
while count != endCount
    total = total + count
    count = count + 1
m0skit0
  • 25,268
  • 11
  • 79
  • 127
1

Here is the solution for EMU8086 :

.stack 100h

.data

msj1  db 'Enter first number: $'

msj2  db 'Enter second number: $'

num1  dw ?  ;FIRST  NUMBER OF INTERVAL.

num2  dw ?  ;SECOND NUMBER OF INTERVAL.     

str   db 6         ;MAX NUMBER OF CHARACTERS ALLOWED (4).
      db ?         ;NUMBER OF CHARACTERS ENTERED BY USER.
      db 6 dup (?) ;CHARACTERS ENTERED BY USER. 

crlf  db 13,10,'$'  ;LINE BREAK.

plus  db '+$'  ;PLUS SIGN TO DISPLAY. 

back  db 8,'$' ;CURSOR WILL MOVE ONE PLACE BACK (TO THE LEFT). 

ekual db '=$'  ;EQUAL SIGN TO DISPLAY. 

suma  dw 0  ;SUMATORY OF ALL NUMBERS BETWEEN NUM1 AND NUM2.

.code          

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

;DISPLAY MESSAGE FOR FIRST NUMBER.
  mov  ah, 9
  mov  dx, offset msj1
  int  21h

;CAPTURE NUMBER AS STRING.
  mov  ah, 0Ah
  mov  dx, offset str
  int  21h

;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
  mov  si, offset str ;PARAMETER FOR STRING2NUMBER.
  call string2number
  mov  num1, bx      ;RETURNED VALUE.

;DISPLAY TWO LINE BREAKS.
  mov  ah, 9
  mov  dx, offset crlf
  int  21h

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

;DISPLAY MESSAGE FOR SECOND NUMBER.
  mov  ah, 9
  mov  dx, offset msj2
  int  21h

;CAPTURE NUMBER AS STRING.
  mov  ah, 0Ah
  mov  dx, offset str
  int  21h

;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
  mov  si, offset str ;PARAMETER FOR STRING2NUMBER.
  call string2number
  mov  num2, bx      ;RETURNED VALUE.

;DISPLAY TWO LINE BREAKS.
  mov  ah, 9
  mov  dx, offset crlf
  int  21h

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

;ASURE FIRST NUMBER IS LESS THAN THE SECOND.
  mov  ax, num1
  cmp  ax, num2
  jbe  fine       ;IF AX < NUM2 JUMP FINE.
  xchg ax, num2   ;EXCHANGE : NUM2=AX, AX=NUM2.
  mov  num1, ax   ;NUM1=NUM2.
fine:

;DISPLAY THE INTERVAL.
  call display_interval  

;WAIT UNTIL USER PRESS ANY KEY.
  mov  ah,7
  int  21h

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

;------------------------------------------
;DISPLAY ALL NUMBERS BETWEEN NUM1 AND NUM2
;SEPARATED BY '+' AND DISPLAYS THE SUM

proc display_interval

interval:    
;ADD CURRENT NUMBER TO SUMA.
  mov  ax, num1       ;AX = CURRENT NUMBER.
  add  suma, ax
;CONVERT CURRENT NUMBER TO STRING TO DISPLAY IT.
  call dollars        ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
  call number2string  ;PARAMETER = AX. RETURNS IN VARIABLE "STR".
;DISPLAY NUMBER CONVERTED TO STRING.
  mov  ah, 9
  mov  dx, offset str
  int  21h
;DISPLAY PLUS SIGN.
  mov  ah, 9
  mov  dx, offset plus
  int  21h
;NEXT NUMBER TO DISPLAY.
  inc  num1
  mov  ax, num1
  cmp  ax, num2
  jbe  interval   ;IF AX <= NUM2 THEN REPEAT.

;DISPLAY THE SUMA.

;DISPLAY BACKSPACE (TO DELETE LAST PLUS SIGN).
  mov  ah, 9
  mov  dx, offset back
  int  21h

;DISPLAY EQUAL SIGN.
  mov  ah, 9
  mov  dx, offset ekual
  int  21h

;CONVERT SUMA TO STRING TO DISPLAY IT.
  call dollars        ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
  mov  ax, suma
  call number2string  ;PARAMETER = AX. RETURNS IN VARIABLE "STR".

;DISPLAY NUMBER CONVERTED TO STRING.
  mov  ah, 9
  mov  dx, offset str
  int  21h

  ret
endp  

;------------------------------------------
;CONVERT STRING TO NUMBER IN BX.
;SI MUST ENTER POINTING TO THE STRING.

proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  inc  si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx,ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.

  ret 
endp    

;------------------------------------------
;FILLS VARIABLE STR WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.

proc dollars                 
  mov  si, offset str
  mov  cx, 6
six_dollars:      
  mov  bl, '$'
  mov  [ si ], bl
  inc  si
  loop six_dollars

  ret
endp  

;------------------------------------------
;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 (STR).

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  

Next is your code with some changes, now it takes two parameters from stack and internally puts them in variables num1 and num2. I'm not taking care of the parameters for all the "print" :

proc display_interval

;RETRIEVE PARAMETERS.
    pop   ax    ;RETURN ADDRESS.
    pop   num2  ;NUM2.
    pop   num1  ;NUM1.
    push  ax    ;RETURN ADDRESS BACK (NECESSARY FOR "RET").

    print msg4
interval:    
    ;ADD CURRENT NUMBER TO SUMA.
      mov  ax, x       ;AX = CURRENT NUMBER.
      add  k, ax
    ;CONVERT CURRENT NUMBER TO STRING TO DISPLAY IT.
      call dollars        ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
      call number2string  ;PARAMETER = AX. RETURNS IN VARIABLE "STR".
    ;DISPLAY NUMBER CONVERTED TO STRING.
      mov  ah, 9
      mov  dx, offset str
      int  21h
    ;DISPLAY PLUS SIGN.
      mov  ah, 9
      mov  dx, offset plus
      int  21h
    ;NEXT NUMBER TO DISPLAY.
      inc  x
      mov  ax, x
      cmp  ax, y
      jbe  interval   ;IF AX <= NUM2 THEN REPEAT.

    ;DISPLAY THE SUMA.

    ;DISPLAY BACKSPACE (TO DELETE LAST PLUS SIGN).
      print back

    ;DISPLAY EQUAL SIGN.
      print equal

    ;CONVERT SUMA TO STRING TO DISPLAY IT.
      call dollars        ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
      mov  ax, k
      call number2string  ;PARAMETER = AX. RETURNS IN VARIABLE "STR".

    ;DISPLAY NUMBER CONVERTED TO STRING.
      mov  ah, 9
      mov  dx, offset str
      int  21h

      ret
endp  

Procedure "display_interval" should be called like this :

mov  ax, 1
push ax      ;FIRST PARAMETER.
mov  ax, 5
push ax      ;SECOND PARAMETER.
call display_interval
  • thanks very much!! And one more question. How can i do if i want jump from procedure the _n_ rows below. It should go through the return value not jump. exampe> calling the proc(row) `CALL proc` and for example the `ret` from procedure jumps 6 rows below the `CALL proc` – Tiestik Apr 24 '15 at 18:04
  • I'm not sure to understand your question. Anyway, if you jump without doing RET, the stack will may have garbage, or maybe not, I would need to see the code to understand what you are after to (post the code so I can check it out), but, if you want to jump n rows below, you can do a normal jump and do the RET after this jump, so the stack is OK. Question: why didn't you accept my answer, is anything wrong with it, didn't it run well? – Jose Manuel Abarca Rodríguez Apr 24 '15 at 18:36
  • no its ok :) i m was just curious about the jump. I will post the code later so you could understand, but right now i have more important question. I m trying to do the procedure of yours(display_interval)with arguments (num1,num2) but its not going well, How can i declare arguments in procedure ? `x:DWORD, y:DWORD` something like this ? – Tiestik Apr 24 '15 at 18:50
  • #1 : push arguments on stack and pop them inside the procedure (remember to pop the return address and push it back). #2 put arguments on registers you are not using at the moment. #3 put arguments in variables declared in data segment. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 18:52
  • To use high-level-language parameters style you will need to use inline assembler. Next is an example with VS2010 C++ : http://stackoverflow.com/questions/29830481/how-to-convert-a-dword-into-a-db/29832271#29832271 . It's a traditional method void number2string ( int value ), but inside it's "inline assembler". – Jose Manuel Abarca Rodríguez Apr 24 '15 at 19:00
  • I try something but its not working at all (post above):D could you demonstrate on specific example like in your post display_interval(just edit) i would understand it faster. And sould it be 3 arguments (sum,num1,num2)or 2(num1,num2) ? – Tiestik Apr 24 '15 at 19:51
  • By pushing them on stack? – Jose Manuel Abarca Rodríguez Apr 24 '15 at 20:05
  • Ok, I just edited my answer to add your code with some changes. I noticed you are using "print", I'm not sure how "print" gets parameters so I just ignored them. Variables "num1" and "num2" are necessary for the internal algorithm. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 20:18
  • print, its just macro(ah,9) and the k,x,y that i put there is ok or shoudnt be it num1,num2,suma ? – Tiestik Apr 24 '15 at 20:23
  • Any name is ok. Notice in my code that I don't use BP or SP. I prefer to get parameters out of the stack with pop and push return address back. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 20:25
  • The algorithm needs two variables (num1 and num2, you can use other names), not two EQU. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 20:37
  • Are you saing the BP is harder ? Could you show me how to get access these 2arguments from BP register – Tiestik Apr 24 '15 at 20:41
  • Using BP is not my style. I prefer to pop the parameters since the beginning and push the return address back to protect the stack from inconsistencies (in my answer, under the comment RETRIEVE PARAMETERS). – Jose Manuel Abarca Rodríguez Apr 24 '15 at 20:45
  • OK :) and back to my first question i tried to describe that jump i was asking earlier with ret instruction. my post edited> http://stackoverflow.com/questions/29819483/assembly-how-to-do-sum-between-two-numbersinterval/29856225#29856225 – Tiestik Apr 24 '15 at 20:57
  • In that case, remove the RET and replace it by JMP to a label several rows after. Remember to do a POP to delete the return address on stack. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 20:58
0

You can use conditional jump to do so. Below, there is a simple code snippet in which ebx contains current number to be added, ecx contains number of times loop will run (i.e, second_number - first_number +1). sum will be stored in eax.

mov eax,0               ; initialise sum with 0
mov ebx,dword[first_number]    ;initialise ebx with first_number
mov ecx,dword[second_number]  
sub ecx,dword[first_number]
inc ecx                 ; ecx content will be end_number - start_number + 1, now
calculation:            ; after calculation sum can be accessed from eax
        add eax,ebx     ; sum = sum + ebx content
        inc ebx         ; ebx = ebx + 1
        dec ecx         ; ecx = ecx - 1
        cmp ecx,0h      ; ecx == 0 ?
        jne calculation ; if not then once again go through calculation.
user148865
  • 326
  • 1
  • 5
  • 19
0
proc display_interval

    push BP                 
    mov BP, SP
    mov AX, [BP+4]
    mov SP, BP
    pop BP

    print msg4
interval:    
    mov  ax, num1       ;AX = CURRENT NUMBER.
    add  suma, ax
    ;CONVERT CURRENT NUMBER TO STRING.
    call dollars        ;FILL "STR" WITH '$'.
    call number2string  ;PARAMETER = AX.

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

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

    inc  num1
    mov  ax, num1
    cmp  ax, num2
    jbe  interval   ;IF AX <= NUM2


    ;BACKSPACE (DELETE LAST +).
    print back
    print equal

    call dollars        ;FILL "STR" WITH '$'.
    mov  ax, suma
    call number2string  ;PARAMETER = AX.

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

    ;-------------------------------------------
    ;IF SUMA IS EVEN RET WILL JUMP FEW ROWS BELOW(d2)
    mov dx,0                ;dividing
    mov bl,suma
    mov ax,bx
    mov cl,2
    div cl                  ;the remainder from division stores in AH
    mov dl,ah
    add dl,48               ;48 ASCII is 0, for compare
    cmp dl,48               ;0?
    je  d2                  
                            ;dividing end
    pop ax
    mov sp,bp
    pop bp
    ret                     ;normal RET

d2: pop ax
    mov dx,583              ;number whitch it jumps from RET
    mov [bp+2],dx
    mov sp,bp
    pop bp
    ret                     ; jumping RET, if suma is even

endp  
Tiestik
  • 61
  • 1
  • 2
  • 6
  • I believe you have inconsistencies in your stack. You push the parameters before doing CALL. So, pop the parameters at the beginning of the procedure (that's my style). It's safer. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 21:14
  • yes is working and one more thing is it possible to do the sum with negative numbers ? – Tiestik Apr 24 '15 at 21:51
  • There is no problem with negative numbers, the problem would be the procedure to convert from number to string because it's made for positive numbers, but you can fix it easily : before calling number2string, if the number is negative, make it positive by multiplying it by -1, call number2string, and add the character '-' at the beginning of the resulting string. – Jose Manuel Abarca Rodríguez Apr 24 '15 at 21:56
  • can you show me how to do if first number is greater ? i tried cmp num1,num2 -> jump if greater an change num1 and num2 but it doesnt working somehow can u edited :) – Tiestik Apr 28 '15 at 08:50
  • Done. Check the comment "ASURE FIRST NUMBER IS LESS THAN THE SECOND" in my original answer. I didn't run the code. You run it and let me know if you have any problem. – Jose Manuel Abarca Rodríguez Apr 28 '15 at 13:56
  • Yes is't working. One thing I edited my post here. It is a entire procedure of mine. Can u tell me what is wrong there. I mean i know what is wrong but how to fix it ? the row `mov bl, suma` its wrong because suma is already a string and these two types do not match. I tried to convert it back to number or more ways how to do it but nothing goes well can u fix it :| – Tiestik Apr 28 '15 at 17:20
  • suma is DW in data segment. Do "mov BX, suma", because BL is DB (one byte), while BX is DW (two bytes). – Jose Manuel Abarca Rodríguez Apr 28 '15 at 17:25
  • ye its working :) and one more :D i found out the exist JPE(Jump If Parity Even) Is it possible to rewrite the hole dividing thing i did to something easier with this JUMP ? – Tiestik Apr 28 '15 at 17:31
  • I'm not sure but I don't think so. Because the PARITY FLAG gets its value from the last operation. It would be necessary to save the parity flag after every division. On the other hand, I don't see how JPE would be useful here. – Jose Manuel Abarca Rodríguez Apr 28 '15 at 17:38
  • hi i have one more question :). I have program and i wanna know lenght of string or basically what this program does ? http://www.fiit.stuba.sk/~bernat/asm/strcmp.exe – Tiestik May 05 '15 at 08:28
  • You need two things : the end-of-string character (0, 13, '$', or any other), and a loop. You start at the beginning of the string (mov si, offset mystring), the loop ends when the end-of-string character is reached. – Jose Manuel Abarca Rodríguez May 05 '15 at 13:55