Search code examples
assemblytasm

TASM code for multiples of n under 100 doesnt show output


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?


Solution

  • 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