Loop Proc1, te devuelve a Proc1, pero antes decrementa el registro CX en una unidad, cuando CX llega a 0, deja de hacer el salto a Proc1... Entonces se trata de saber que valor ingresas en el registro CX.
Si miramos el código, al registro CX, no se le ha asignado explícitamente ningún valor, luego contendrá la basurilla que reste de otro programa, si más adelante colocas un valor en CL, pero no sabemos cual hay en CH, luego...

Típicamente un bucle lleva la estructura:
Prueba a asignar a contador un valor arbitrario cada vez, por ejemplo 13, ejecuta paso a paso y verás como el bucle retorna una y otra vez al 'Inicio', y cólo cuando CX valga 0, ejecuta el código tras el bucle.
Dado que dices "n números ingresados", Contador debería valer ese 'n'. Si 'n' no es conocido, porque se debe ejecutar una y otra vez hasta que el usuario tome una decisión al respecto, entonces el bucle que debe usarse no va por Loop, mejor LOOPNE, o LOOPNZ por ejemplo haciendo que cuando el usuario quiera terminar pulse una determinada tecla, tu haces un TEST entre el valor de la letra esperada (Q) y el valor de la letra introducida por el usuario, y acto seguido saltas en función del resultado del test... a diferencia de otros lenguajes, el ensambalador permite una infinidad de opciones para hacer lo mismo. compruebas si la tecla pulsada es la deseada, en cuyo caso puedes hacer un XOR CX CX (que cambia su contenido a 0, y entonces usas LOOPNZ), cuando CX sea 0, saldrá del bucle... en este caso el salto está condicionado, por la pulsación de una tecla concreta (la 'Q' por ejemplo de "Quit")...
Y tu código quedaría controlado tal que así:
Al llegar a Loop, si la tecla introducida es distinta de la esperada, se incrementa CX, entonces CX=2, luego Loop decrementa CX, y CX vuelve a valer 1.
En cambio, si el númnero recibido es igual al valor ASCII de Q (81) el test devuelve 'True', y por tanto saltamos el incremento de CX, como vale 1, cuando llegue a LOOP decrementa 1, vale 0 y por tanto sale ya del bucle.
En resumen:
- Fíjate que tu no tienes claro (yo por lo menos leyendo tu código), el valor de CX, así que no hay forma de saber cuando llega a cero...
- LOOP decrementa CX en 1 cada vez que se ejecuta y si CX vale 0, sale fuera del bucle.
- Si el condicional de salida depende de algún factor más, puedes o bien controlar directamente CX (como te muestro en el ejemplo), o bien usar otras variantes de LOOP, LOOPE, LOOPZ, LOOPNE, LOOPNZ, o incluso alguna instrucción condicional de salto... (por ejemplo JNE, podría saltar fuera del bucle directamente, es buena práctica al inicio, tener una única salida de un procedimiento, cuando tengas buen control del código, no te importará que se salga desde más de una parte)...
Si miramos el código, al registro CX, no se le ha asignado explícitamente ningún valor, luego contendrá la basurilla que reste de otro programa, si más adelante colocas un valor en CL, pero no sabemos cual hay en CH, luego...



Típicamente un bucle lleva la estructura:
Código (asm) [Seleccionar]
MOV CX, Contador
Inicio:
... codigo a repetir
LOOP Inicio
cuando CX valga 0
...codigo despues del bucle
Prueba a asignar a contador un valor arbitrario cada vez, por ejemplo 13, ejecuta paso a paso y verás como el bucle retorna una y otra vez al 'Inicio', y cólo cuando CX valga 0, ejecuta el código tras el bucle.
Dado que dices "n números ingresados", Contador debería valer ese 'n'. Si 'n' no es conocido, porque se debe ejecutar una y otra vez hasta que el usuario tome una decisión al respecto, entonces el bucle que debe usarse no va por Loop, mejor LOOPNE, o LOOPNZ por ejemplo haciendo que cuando el usuario quiera terminar pulse una determinada tecla, tu haces un TEST entre el valor de la letra esperada (Q) y el valor de la letra introducida por el usuario, y acto seguido saltas en función del resultado del test... a diferencia de otros lenguajes, el ensambalador permite una infinidad de opciones para hacer lo mismo. compruebas si la tecla pulsada es la deseada, en cuyo caso puedes hacer un XOR CX CX (que cambia su contenido a 0, y entonces usas LOOPNZ), cuando CX sea 0, saldrá del bucle... en este caso el salto está condicionado, por la pulsación de una tecla concreta (la 'Q' por ejemplo de "Quit")...
Y tu código quedaría controlado tal que así:
Código (asm) [Seleccionar]
MOV CX, 1 <-- poner un valor en el contador
Inicio:
.... tu codigo (entrada de datos por parte del usuario)
TEST teclaesperada "Q", contra valor entrado
JNE FinOpera <--- SALTAR si igual (o si no cero JNZ)
INC CX
.... tu código para sumar el nuevo valor entrado (distinto de Q)
FinOpera: <--- punto de salto si usuario pulsa tecla Q (salir)
LOOPNZ Inicio
Al llegar a Loop, si la tecla introducida es distinta de la esperada, se incrementa CX, entonces CX=2, luego Loop decrementa CX, y CX vuelve a valer 1.
En cambio, si el númnero recibido es igual al valor ASCII de Q (81) el test devuelve 'True', y por tanto saltamos el incremento de CX, como vale 1, cuando llegue a LOOP decrementa 1, vale 0 y por tanto sale ya del bucle.
En resumen:
- Fíjate que tu no tienes claro (yo por lo menos leyendo tu código), el valor de CX, así que no hay forma de saber cuando llega a cero...
- LOOP decrementa CX en 1 cada vez que se ejecuta y si CX vale 0, sale fuera del bucle.
- Si el condicional de salida depende de algún factor más, puedes o bien controlar directamente CX (como te muestro en el ejemplo), o bien usar otras variantes de LOOP, LOOPE, LOOPZ, LOOPNE, LOOPNZ, o incluso alguna instrucción condicional de salto... (por ejemplo JNE, podría saltar fuera del bucle directamente, es buena práctica al inicio, tener una única salida de un procedimiento, cuando tengas buen control del código, no te importará que se salga desde más de una parte)...