Hey guys can you help? I dont know how to do sum between two numbers For example :
first number>1
second number>5
sum w
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.
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
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
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