This is what the code does. Say the user inputs the number 20. it multiplies this with the counter CX, set to 1, and increases for each iteration. when the result reaches or exceeds 100 (4 iterations for the number 20) it goes back and prints all of them by pushing and popping into the stack. Each number is added, then separated to single digits, and then displayed using the 02 function.
MOV CX, 01D
MOV AX, 0
MOV DX, BX ; BX contains the number
MOV DI, 01 ;
MOV SI, 01 ; used for addressing offsets of BX
MULTIPLY:
MOV AX, DX
MUL CX
CMP AX, 100D
JGE FINISHED
MOV [BX+DI], AX
INC CX
INC DI ; will be changed to ADD DI, 2
JMP MULTIPLY
This snippet has the problem. Im trying to get this to multiply the input with 1, then 2 then 3 and so on until the result reaches 100. What have I missed here?
One problem in your code : before label multiply
you store the input number in DX :
MOV DX, BX ; BX contains the number
but after the label multiply
you use mul
, that destroys DX. The solution is to use another register, BP for example, instead of DX.
Another important problem is that you are storing the multiples in [BX+DI]
, but there is no variable in the data segment where BX is pointing to. The solution is to create an array ("buf").
Now let's apply both solutions to your original code, I added a comma to separate the numbers, changes are pointed by arrows (;<===
) :
.MODEL SMALL
.STACK 100H
.DATA
S1 DB 13,10, "Enter a number below 100 :" , '$'
S3 DB 13,10, "The multiples are: ", '$'
buf dw 100 dup(?) ;<=== ARRAY OF MULTIPLES.
comma db ",$" ;<=== SEPARATOR BETWEEN MULTIPLES ON SCREEN.
.CODE
MAIN PROC
MOV AX,@DATA
MOV DS,AX
LEA DX, S1
MOV AH, 09 ; ENTER A NUMBER?
INT 21H
CALL INPUT ;ACCEPTS A NUMBER
LEA DX, S3
MOV AH, 09 ; THE MULTIPLES ARE:
INT 21H
MOV CX, 01D
MOV AX, 0
MOV bp, BX ;<=== PRESERVE INPUT NUMBER IN BP.
mov di, offset buf ;<=== DI POINTS TO ARRAY OF MULTIPLES.
;MOV DI, 01
;MOV SI, 01
MULTIPLY: ;where the good stuff happens
MOV AX, BP ;<=== MUL WILL CHANGE DX, THAT'S WHY WE USE BP.
MUL CX ;AX*CX = RESULT IN DX:AX.
CMP AX, 100D
JGE FINISHED
MOV [di], AX ;<=== STORE MULTIPLE IN ARRAY.
INC CX
;INC DI
add di,2 ;<=== EACH MULTIPLE IS TWO BYTES.
JMP MULTIPLY
FINISHED:
;WHEN PREVIOUS BLOCK FINISHES "DI" POINTS AT THE END OF "BUF".
;MOV CX, 0 ;<=== CX IS ZERO 6 LINES BELOW.
MOV DX,0
MOV BX,10D
mov si, offset buf ;<=== SI POINTS TO THE ARRAY OF MULTIPLES.
OUTER:
MOV CX, 0 ;<=== CX MUST BE HERE (IT'S DIGIT COUNTER).
MOV AX,[SI] ;<=== RETRIEVE A MULTIPLE FROM ARRAY.
SHOW: ;push to stack and print digit by digit
MOV DX,0
DIV BX
PUSH DX
INC CX
CMP AX,0
JNZ SHOW
PRINT:
MOV DX,0
MOV AH,02H
POP DX
ADD DL,30H
INT 21H
LOOP PRINT
;DISPLAY COMMA SEPARATOR.
mov ah,9
mov dx,offset comma
int 21h
;INC SI
add si, 2 ;<=== NEXT MULTIPLE TO DISPLAY.
CMP SI, DI ;<=== IF SI IS NOT IN THE END
JNE OUTER
INPUT PROC
ACCEPT:
MOV AH,01H
INT 21H
CMP AL,0DH
JZ CONTINUE
MOV AH,0
SUB AL,30H
PUSH AX
MOV AX,10D
MUL BX
POP BX
ADD BX,AX
JMP ACCEPT
CONTINUE:
RET
INPUT ENDP
EXIT:
MOV AH,4CH
INT 21H
ENDP MAIN
END MAIN