; Listing10-2.asm
;
; A program that demonstrates macros
; for the yield, foreach, and endfor
; iterator statements.


            option     casemap:none
            .nolist
            include    aoalib.inc
            include    aoaProcs.inc
use1var      =     1                ;Use Ver1 _push and _pop
            include    ctPushPop.inc
            includelib aoalib.lib
            .list
            
; Program title:

            .const
             align  word
ttlStr       byte   "Listing 10-2", 0

            .code
            
; Macros to implement iterators:

yield       macro
            push    qword ptr [rbp]
            call    qword ptr [rbp+8]
            endm

iterStk     textequ <>      
foreach     macro   iterator
            local   failureAdrs
            _push   (iterStk, failureAdrs)
            lea     rax, failureAdrs
            push    rax
            call    iterator
            push    rbp
            mov     rbp, [rsp+16]
            endm
            
endfor      macro
            local   failureAdrs
            pop     rbp
            ret     8
failureAdrs _pop    (iterStk)
failureAdrs:
            endm
            

            

; iterator range( start:dword, stop:dword )

        parms range, rbp, 24,       \
              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
            
            yield

; Move on to next iteration of the loop

            inc  range$start
            jmp  ForEverLbl

ForDone:
            pop     rbp
            add     rsp, 8
            ret
range       endp


;--------------------------------------------------
;
; 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
            foreach range       ;Call the iterator

; Body of the foreach loop:

            mov  edx, eax       ;Display i’s value
            call print
            byte "%d", nl, 0

            endfor
            
            
            leave
            ret
        
asmMain     endp
            end