Search code examples
loopsassemblynested-loopstasm

Two loops nested inside another loop in x86 assembly


I've got a problem looping in assembly language.

When we want to use the counter register for looping in nested loop, what we first do is move the value of counter register into the stack for outer loop and then fetch it back when we're done with the inner loop, this way we're capable of using one counter register for looping into the nested loop with different number of iteration on each loop.

But what about nested loop inside a nested loop?

I want to print a pyramid made of of the character S. What I am getting is,

SSSSSSSSSS
SSSSSSSSS
SSSSSSSS
SSSSSSS
SSSSSS
SSSSS
SSSS
SSS
SS
S

What I actually want is,

 SSSSSSSSSS
  SSSSSSSS
   SSSSSS
    SSSS
     SS
     S

Here is my code for the program

MOV BX,10           ; HOLD 10 IN BX FOR INNER LOOP
     MOV AX,0           ; START ITERATIONS FROM 0
     MOV CX,10          ; MAX NUMBER OF ITERATIONS

    L2:

        PUSH CX         ;PUSH CX IN A STACK
        MOV CX,BX       ;STORE NEW VALUE IN CX FOR INNER LOOP ITERATION

            L1:

                MOV DX, [SI]               ; MOVE THE STRING INTO DX
                MOV AH,02H                 ; DISPLAY EVERYTHING FROM DX
                INT 21H

            LOOP L1

        MOV DX,0AH     ;PRINT LINE FEED AFTER PRINTING EACH LINE OF ASTERIKS
        MOV AH,02H
        INT 21H

        SUB BX,01     ;DECREASE THE VALUE OF BX BY 1

        POP CX        ;RESTORE ORIGINAL VALUE OF CX FOR OUTER LOOP
        ADD AX,01     ;INCREMENT VALUE OF AX BY 1

    LOOP L2


     MOV AH, 4CH                  ;RETURN CONTROL TO DOS
     INT 21H

In order to achieve what I want, i need to add another loop inside the nested loop that prints space characters (i.e 020H). But for this I need another counter register and I am not able to do it. How can I solve this problem?


Solution

  • About like that?

    L2:
    
        PUSH CX         ;PUSH CX IN A STACK
    
        ; insert this
        MOV CX, 10      ; width of your tree = 10
        SUB CX, BX      ; subtract length of "s" string
        SHR CX, 1       ; divide CX by 2 => number of spaces at the beginning
        JCXZ endL3      ; no spaces? don't do anything
    
           L3:
                MOV DX, 20H ; space character
                MOV AH,02H                 ; print space
                INT 21H
    
            LOOP L3
    
        endL3:
    
        MOV CX,BX       ;STORE NEW VALUE IN CX FOR INNER LOOP ITERATION
    
            L1:
    
                MOV DX, [SI]               ; MOVE THE STRING INTO DX
                MOV AH,02H                 ; DISPLAY EVERYTHING FROM DX
                INT 21H
    
            LOOP L1
    
        MOV DX,0AH     ;PRINT LINE FEED AFTER PRINTING EACH LINE OF ASTERIKS
        MOV AH,02H
        INT 21H
    
        SUB BX,01     ;DECREASE THE VALUE OF BX BY 1
    
        POP CX        ;RESTORE ORIGINAL VALUE OF CX FOR OUTER LOOP
        ADD AX,01     ;INCREMENT VALUE OF AX BY 1
    
    LOOP L2
    

    Btw, for what purpose are you initializing and incrementing AX? You overwrite it anyway when moving data to AH/AL.