LOOP subtracts 1 from CX and then jumps if CX is not zero. The decrement does not change any flag. Load CX with the count, put the body between a label and the LOOP, and the body runs CX times:
MOV CX, 5AGAIN1:MOV AL, CL ; the counter itselfADD AL, "0" ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print the character in DLINT 21hLOOP AGAIN1 ; CX - 1, back while CX <> 0
It behaves like DEC CX / JNZ except for the flags: LOOP touches none, so a flag set inside the body survives to the next round. That makes it the natural partner of ADC in multi-word additions, where CF must carry from one word to the next.
Pitfalls
Entered with CX = 0, the first decrement gives FFFFh and the loop runs 65536 times; guard with JCXZ. LOOP is SHORT only (opcode E2h, −128..+127 bytes back) and MASM will not lengthen it; when the body grows too big, switch to DEC CX / JNZ TOP1, which it can. Nested loops share CX, so save the outer count:
MOV CX, 10 ; outer countOUTER1:PUSH CX ; keep itMOV CX, 20 ; inner countINNER1:; ... inner body ...LOOP INNER1POP CX ; outer count backLOOP OUTER1
Later CPUs
In 32-bit code the 386 counts in ECX instead of CX. The instruction is otherwise unchanged and still short-range only.