Search code examples
assemblyx86tasm

How does this x86 assembly program work


Here's an x86 asm program which prints a 'counter' from 000 to 999 in the middle of the screen which works fine (I didn't write it). The issue is I'm trying to understand how it works. What the use of DIV and the STACK are in THIS program.

How will the program know how to go e.g. from 009 to 010. What's the inner loop?

I know how it clears the screen and prints to the middle of the screen and I know about the clock delay function.

What purpose do DIV, PUSH, and POP serve in this program?

Basically I'm trying to trace it and understand the functions used. I'm still quite a beginner, please help. Thanks.
Here's the code:

.MODEL SMALL
.STACK 64
.DATA
CNT DW 0h
.CODE
MOV AX,@data
MOV DS,AX

MOV AX, 0600H
MOV BH,07
MOV CX, 0000
MOV DH,12
MOV DL,39       

INT 10H

MOV AX,0600H
MOV BH,07 
MOV CX,0000 
MOV DX,184FH
INT 10H         

MOV CNT,0

L1: MOV AH,02h
MOV BH,0
MOV DH,12
MOV DL,39
INT 10h         

MOV AX,CNT
MOV BL,10
DIV BL              
PUSH AX

MOV AH,00
MOV BL,10
DIV BL                
PUSH AX               
MOV DL,AL
ADD DL,48
MOV AH,02h
INT 21h

POP AX
MOV DL,AH
ADD DL,48       
MOV AH,02h
INT 21h

POP AX
MOV DL,AH
ADD DL,48
MOV AH,02h      
INT 21h             

MOV CX, 0007h
MOV DX, 2120h 
MOV AH, 86H         
INT 15H             

INC CNT
CMP CNT,999
JBE L1  

MOV AH,4ch          
INT 21h
END

Solution

  • How will the program know how to go e.g. from 009 to 010, what's the inner loop ?

    The inner loop is formed from the L1 label to the JBE L1 instruction. The memory CNT holds the counter that is being displayed. It is initialized to zero from the executable and is incremented (INC CNT), compared to 999 and loop while it is below or equal.

    What purpose does DIV, PUSH and POP serve in this program ?

    The purpose is to split up the CNT value into separate digits and display them. DIV BL divides AX by BL and stores the quotient in AL and remainder in AH.

    Perhaps the best explanation of what this is doing is through an example. Suppose, CNT had a value of 123. To compute each printable digit, we would divide by 10 and get a quotient of 12 with a remainder of 3. Now, 3 is what we need to print last so we need to store that in the stack. Then we would repeat this process getting 2 and then 1. Now, we can print out 1, pop out the 2 in the stack and print that and then pop out the 3 and print that so we have 123 printed out.

    The code segment

    MOV DL,AH
    ADD DL,48       
    MOV AH,02h
    INT 21h
    

    is responsible for printing each digit. It first gets the remainder which was stored in AH, add 48 (030h) to get the ASCII digit ('0' = 30h .. '9' = 39h) and then calls function 02h/int21 to print a single character to the screen.