Looping Constructs

 

Operations are performed repeatedly via loops. In higher level languages, loops are hand-manufactured via conditions and branches (If Statement and Gotos) or using language defined structured loop statements. The latter include Repeat, While, and For Statements.

 

Our first assembler example implements a hand-manufactured loop, the one you should avoid. The loop body is repeated until a particular value (sentinel) is found. However, the loop body is entered unconditionally; hence this resembles a Repeat Statement.

 

The second assembler example knows the iteration count at the time of assembly, hence the x86 provided loop instruction can be used. This loop body can be characterized as a For Statement which is known to be executed at least once.

 

The third example does not know the number of iterations at the time of assembly. Hence, before entering the loop body for the first time, a check must be made for the loop count to be less than or equal to zero. If so, the body is bypassed; else the body is entered and executed countably many times. Thus, the loop resembles a C-style For Statement.

 

Synopsis

·        Motivation

·        Definitions

·        Repeat Loop with Sentinel

·        For Loop with A-Priori Loop Count

·        For Loop with Iteration Count Unknown at Assembly Time

·        Exercises

 

Motivation

·        Repeated execution necessary, since number of steps varies with data values

·        Special operations provided by hardware speed-up loop overhead

·        On x86 architecture with few registers, cx takes over special loop-count role

·        On x86, loop instructions does the following (in Pseudo Code):

·        loop next is executed: (if (--cx) > 0 ) goto next;

·        New x86 instruction to test for dangerous, initial zero value, is: jcxz on x86 architecture

 

 

 

Definitions

Branch:

Transfer of control to a destination that is generally not the instruction following the branch. Synonym: Jump. The destination is an explicit or implicit operand of the branch instruction.

Countable Loop:

Loop, in which the number of iterations can be computed (is known) before the loop body starts.

For Loop:

High-level construct implementing a countable loop.

Hand-Manufactured Loop:

Most general type of loop. The number of iterations cannot be computed before, not even during the execution of the loop. Generally, the number of iterations depends on data that are input via read operations. Also, the number of steps may depend on the precision of a computer (floating-point) result and thus is not known until the end.

Jump:

Synonym for Branch. Transfer of control to a destination that is generally not the instruction following the jump. The destination is an explicit or implicit operand of the jump.

Loop Body:

Program portion executed repeatedly. This is the actual work to be accomplished. The rest is loop overhead. Goal to minimize that overhead.

Repeat Loop:

Loop in which the body is entered unconditionally. The number of iterations is generally not known until the loop terminates.

Sentinel:

Predefined value, against which an operand is compared during each operation. When the sentinel is found, a special operation takes place. Usually, a loop body terminates.

While Loop:

Loop in which the body is entered after first checking whether the condition for execution is true. If not, the body is not executed. This is also used as the termination criterion. The number of iterations is generally not known until the loop terminates.


 Repeat Loop with Sentinel

 

·        We define character string in data segment, all ‘0’..’f’ hex digits

·        Data area is named ‘chars’ and being used as address (data offset)

·        Sentinel for loop termination is ‘#’

·        Register bx used as index register

·        Note that only bx, si, di, and bp ccan be used for indexing

·        Learn cmp instruction, which compares by subtracting, and then sets flags

·        Learn to know conditional (jcc) and unconditional jump (jmp)

·        See use of labels as destinations of jumps

·        Output of program is:                                  0123456789abcdef

 

; Source file: loop1.asm

; Date:        2-2-1997

; Purpose:     use, syntax of indexing char array w. sentinel

 

start         macro              ; no parameters

              mov  ax, @data     ; @data predefined macro

              mov  ds, ax        ; now data segment reg set

              endm               ; end macro: start

    

termin        macro ret_code     ; 1 parameter: return code

              mov  ah, 4ch       ; terminate: set ah + al

              mov  al, ret_code  ; any errors? If /= 0

              int  21h           ; call DOS for help

              endm               ; end macro: termin

 

Char_Out      =    2h

Sentin        =    '#'

 

              .model small

              .data

chars         db   "0123456789abcdef", Sentin

 

              .code

main:         start

 

              mov  ah, Char_Out  ; set up ah for DOS call

              mov  bx, 0         ; to index string, init 0

 

next:         mov  dl, chars[bx] ; find next char

              inc bx            ; increment index register

              cmp  dl, Sentin    ; found sentinel?

              je   done          ; yep, so stop

              int 21h           ; nop, so print it

              jmp  next          ; try next one; could be sentinel

done:         termin    0         ; no errors if we reach

              end       main      ; start here!


 For Loop with A-Priori Loop Count

 

·        Again we define character string in data segment, all ‘0’..’f’ hex digits

·        Have no sentinel

·        Assume that loop is executed exactly 16 times, known a-priori

·        Again use register bx as index register

·        Learn loop instruction, which tracks loop count and conditional branch

·        Loop instruction on x86 subtracts 1 from cx

·        If cx = 0, fall through; else branch to target, which is part of instruction

·        Output of program is:                                  0123456789abcdef

 

 

; Source file: loop2.asm

; Purpose:     use, syntax of indexing char array

;             loop is "countable" we know # of elements

;             b 4 start of loop; we know at assembly time

 

              . . . same macros start, termin

 

Char_Out      =    2h

Num_El        =    10h           ; 16 elements in chars array[]

 

              .model    small

 

              .data

chars         db        "0123456789abcdef"

 

              .code

main:         start

 

              mov  ah, Char_Out  ; set up ah for DOS call

              mov  bx, 0         ; initial index off 'chars'

              mov  cx, Num_El    ; we know # iterations a priori

 

next:         mov  dl, chars[bx] ; find next char

              inc bx            ; increment index register

              int 21h           ; print it

              loop next          ; try next one; could be 0: end


  For Loop with Iteration Count Unknown at Assembly Time

 

·        Again we define character string in data segment, all ‘0’..’f’ hex digits, no sentinel

·        Assume iteration count is not known a-priori

·        Again use register bx as index register

·        Must check whether cx is less than or equal to zero

·        If so: bad news: Looping will be excessive

·        Loop instruction on x86 subtracts 1 from cx; should start with positive value

·        New instruction jcxz: if cx is already zero at start, branch and don’t enter loop body

·        Output of program is:                                  0123456789abcdef

 

; Source file: loop3.asm

; Purpose:     use, syntax of indexing char array

;             loop is "countable"; this time we know # of

;             elements b 4 start of loop; but NOT at assembly time

 

          .model    small

              .data

chars         db   "0123456789abcdef"

 

              .code

main:         start

 

              mov  ah, Char_Out       ; set up ah for DOS call

              mov  bx, 0              ; initial index off 'chars'

              ; let's assume that # elements is read at run-time

              ; here we just fake this reading by brute-force setting

              ; but the point is: The # could be non-positive!

         

              mov  cx, 16             ; pretend we read value of cx

              cmp  cx, 0              ; then test if cx < 0

              jl   done_neg           ; if it is, jump

              jcxz done_zero          ; if it is zero, jump also

              ; if we reach this:     ; cx is positive

         

next:         mov  dl, [chars][bx]    ; find next char

               inc bx                 ; increment index register

              int 21h                ; output next character

              loop next               ; try next one; could be end

         

done:         termin    0             ; no errors if we reach

done_neg:     termin    1             ; another error code. Not 0

done_zero:    termin    2             ; an yet another error

 

              end       main          ; start here!


 Exercises

 

t.b.d.