; Listing10-1.asm
;
; A program that demonstrates a
; simple range iterator.


            option     casemap:none
            .nolist
            include    aoalib.inc
            include    aoaProcs.inc
            includelib aoalib.lib
            .list
            
; Program title:

            .const
             align  word
ttlStr       byte   "Listing 10-1", 0

            .code

; iterator range( start:dword, stop:dword )

        parms range, rbp, 0,        \
              dynamicLink:qword,    \
              yieldAdrs:qword,      \
              failAdrs:qword,       \
              start:dword,          \
              stop:dword
              
range       proc
            push rbp
            mov  rbp, rsp
            
            mov  edx, range$start
            mov  r8d, range$stop
            call print
            byte "in range, %d to %d", nl, 0

ForEverLbl:
            mov  eax, range$start
            cmp  eax, range$stop
            jg   ForDone
            
; "Magic" yield operation:

            push range$dynamicLink   ;Caller’s RBP
            call range$yieldAdrs

; Move on to next iteration of the loop

            inc  range$start
            jmp  ForEverLbl

ForDone:
            pop  rbp
            add  rsp, 8    ;Remove return address
            ret  16        ;Use failure address as return and
range       endp           ; pop parameters
;--------------------------------------------------
;
; Here is the main assembly language function.
            
            public  asmMain
asmMain     proc
            push    rbp
            mov     rbp, rsp
            sub     rsp, 80
            
            mov  eax, 10        ; Push stop parameter value.
            push rax            ; Remember, push in reverse order!
            mov  eax, 1         ; Push start parameter value
            push rax
            lea  rax, ForDone   ;Push the failure/end loop address
            push rax
            call range          ;Call the iterator

; Body of the foreach loop:

            push rbp            ;Preserve iterator’s rbp value
            mov  rbp, [rsp+16]  ;Get original RBP value passed by range
            mov  edx, eax       ;Display i’s value
            call print
            byte "%d", nl, 0
            pop  rbp            ;Restore iterator's RBP value
            ret  8              ;Return and clean RBP off stack

; After the foreach loop:

ForDone:                
            leave
            ret
        
asmMain     endp
            end