Search code examples
assemblyx86-16dos

I wrote this code to print an integer in decimal taken as user input, but I can't understand what step is wrong?


.MODEL SMALL
.STACK 100H
.DATA
    MSG1 DB " Enter first number  : ",0Ah,0Dh,'$'
    MSG2 DB " The number is: ",0ah,0dh,'$'
.CODE
   MAIN PROC
        MOV AX,@DATA
        MOV DS,AX
        LEA DX,MSG1
        MOV AH,09H
        INT 21H

    L1:  
        MOV AH,01H
        INT 21H
        XOR AH,AH
        CMP AL,13
        JE L2
        MOV DX,0H
        MOV DX,AX
        ADD DX,30H
        PUSH DX
        JMP L1

    L2:
        LEA DX,MSG2
        MOV AH,09H
        INT 21H

    L3: POP DX
        MOV AH,02H
        INT 21H
    LOOP L3

        MOV AH,4CH
        INT 21H
        END MAIN
    MAIN ENDP

Solution

  • The intake part has many superfluous instructions and fails to count the number of PUSH's that you do.

    L1:  
        MOV AH,01H
        INT 21H
        XOR AH,AH         <<< Superfluous
        CMP AL,13
        JE L2
        MOV DX,0H         <<< Superfluous
        MOV DX,AX         <<< Superfluous
        ADD DX,30H        <<< Superfluous
        PUSH DX
        JMP L1
    

    This is a better version:

        XOR CX,CX      <<< This you need
    L1:  
        MOV AH,01H
        INT 21H        <<< gives AL
        CMP AL,13
        JE L2
        PUSH AX        <<< AL is already a character! No need to add 30H.
        INC CX         <<< This you need
        JMP L1
    

    To use the LOOP instruction you need to setup the CX register beforehand (see above). In case no number was inputted, CX will be zero, so you have to test for it:

        JCXZ L4
    L3:
        POP DX         <<< DL is a character
        MOV AH,02H
        INT 21H
        LOOP L3
    L4:
        MOV AH,4CH
        INT 21H
    

    As @Tommylee2k already remarked, the output will be in reverse. This is probably not your intention. However to get that right, using the stack is not the optimal solution. Better use a simple memory buffer.