How to make a loop in x86 assembly language?

130,415

Solution 1

mov cx,3

loopstart:
   do stuff
   dec cx          ;Note:  decrementing cx and jumping on result is
   jnz loopstart   ;much faster on Intel (and possibly AMD as I haven't
                   ;tested in maybe 12 years) rather than using loop loopstart

Solution 2

Yet another method is using the LOOP instruction:

mov  cx, 3

myloop:
    ; Your loop content

    loop myloop

The loop instruction automatically decrements cx, and only jumps if cx != 0. There are also LOOPE, and LOOPNE variants, if you want to do some additional check for your loop to break out early.

If you want to modify cx during your loop, make sure to push it onto the stack before the loop content, and pop it off after:

mov  cx, 3

myloop:
    push cx
    ; Your loop content
    pop  cx

    loop myloop

Solution 3

Use the CX register to count the loops

mov cx, 3
startloop:
   cmp cx, 0
   jz endofloop
   push cx
loopy:
   Call ClrScr
   pop cx
   dec cx
   jmp startloop
endofloop:
   ; Loop ended
   ; Do what ever you have to do here

This simply loops around 3 times calling ClrScr, pushing the CX register onto the stack, comparing to 0, jumping if ZeroFlag is set then jump to endofloop. Notice how the contents of CX is pushed/popped on/off the stack to maintain the flow of the loop.

Solution 4

.model small
.stack 100h
.code 
Main proc
Mov cx , 30 ; //that number control the loop 30 means the loop will 
;excite 30 time 
Ioopfront:
Mov ah , 1
Int 21h 
Loop loopfront; 

this cod will take 30 character

Share:
130,415
Admin
Author by

Admin

Updated on July 26, 2022

Comments

  • Admin
    Admin almost 2 years

    I have written the code so far as:

    .code
    
    main
     Clrscr
    
      mov dh,10            ;row 10
    
      mov dl,20            ;column 20
    
      call Gotoxy          ;locate cursor
    
      PromptForIntegers  
    
        WriteString       ;display string
        ReadInt           ;input integer
      ArraySum
    
        WriteString       ;display string
        WriteInt          ;display integer
    
    DisplaySum  ENDP
    
    END main
    

    How do I get it to repeat the same steps three times using a loop, clearing the screen after each loop iteration?

  • PA.
    PA. over 14 years
    you may use loop loopstart instead of dec cx and jnz loopstart as long as do stuff preserves the cx register
  • PA.
    PA. over 14 years
    a couple of optimizations: (1)you may use jcxz label instead of cmp cx,0 and jz label. (2) you may use loop label instead of dec cx and jnz label
  • Jeff B
    Jeff B over 14 years
    @PA: Preserving cx is necessary even if you don't use loop.
  • Jeff B
    Jeff B over 14 years
    @PA: Depending on your processor, jcxz label and cmp/jz are equivalent. Recent x86 processor use macro-fusion to combine cmp/jmp instructions into a single cycle instruction, essentially replicating jcxz behavior on the fly.
  • Vincenzo Pii
    Vincenzo Pii over 12 years
    This is absolutely correct since the question is about looping three times. However, the question title is much more generic and I think it may be useful to add that, if cx value came from a variable and not from a constant, a JBE zero instruction, to jump to the loopend before entering the loop, would be needed.
  • Anderson Green
    Anderson Green about 11 years
    Which variable or register is being used as the loop counter here?
  • kirbyfan64sos
    kirbyfan64sos over 10 years
    @AndersonGreen: cx.
  • Peter Cordes
    Peter Cordes about 8 years
    loop is slow, and using it is not a good habit. If you need ecx for something inside your loop (e.g. a shift instruction), then just use a different register for the loop counter. Having a push/pop in the loop-counter dependency chain is just silly. Usually loops need some kind of induction variable, so just test that. e.g. increment a pointer by 4 each time through the loop, and cmp / jb against an end pointer as the loop condition.
  • Peter Cordes
    Peter Cordes about 8 years
    This loop is incredibly inefficient. If a loop might run zero times, then test the counter outside the loop. Then use a conditional branch at the end of the loop. And use a register that you won't need to push/pop as your loop variable. (e.g. a call-preserved register like (e/r)bx or (e)si if there are function calls in your loop.). And Jeff B is right: cmp/jz or dec/jz is cheaper than jcxz on modern CPUs like Intel Haswell. See agner.org/optimize
  • Peter Cordes
    Peter Cordes about 8 years
    Works, but slower than dec/jnz.
  • Peter Cordes
    Peter Cordes about 8 years
    If you're making a function call inside the loop, use a different register for your counter: bx is preserved across function calls in 32 and 64bit ABIs, and I assume also in 16bit ABIs. And yes, loop is slow. Don't use it, and don't fall into the trap of thinking that you need a separate loop counter if you can instead just test a pointer or something that you already need in the loop. (e.g. cmp si,bx / jb at the bottom.)
  • Michael
    Michael about 8 years
    What does this add that wasn't already explained in the other answers posted years ago?