home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH12 / EX12_1.ASM next >
Encoding:
Assembly Source File  |  1996-02-18  |  8.1 KB  |  399 lines

  1. ; EX12_1.asm
  2. ;
  3. ; Program to support the laboratory exercise in Chapter 12.
  4. ;
  5. ; This program combines iterators, passing parameters as parameters,
  6. ; and procedural parameters all into the same program.
  7. ;
  8. ;
  9. ; This program implements the following iterators (examples written in panacea):
  10. ;
  11. ; program EX12_1;
  12. ;
  13. ; fib:iterator(n:integer):integer;
  14. ; var
  15. ;    CurIndex:integer;
  16. ;    Fn1:     integer;
  17. ;    Fn2:     integer;
  18. ; endvar;
  19. ; begin fib;
  20. ;
  21. ;    yield 1;    (* Always have at least n=0 *)
  22. ;    if (n <> 0) then
  23. ;
  24. ;        yield 1;    (* Have at least n=1 at this point *)
  25. ;
  26. ;        Fn1 := 1;
  27. ;        Fn2 := 1;
  28. ;        foreach CurIndex in 2..n do
  29. ;
  30. ;            yield Fn1+Fn2;
  31. ;            Fn2 = Fn1;
  32. ;            Fn1 = CurIndex;
  33. ;
  34. ;        endfor;
  35. ;    endif;
  36. ;
  37. ; end fib;
  38. ;
  39. ;
  40. ;
  41. ; UpDown:iterator(n:integer):integer;
  42. ; var
  43. ;    CurIndex:integer;
  44. ; endvar;
  45. ; begin UpDown;
  46. ;
  47. ;    foreach CurIndex in 0..n do
  48. ;
  49. ;        yield CurIndex;
  50. ;
  51. ;    endfor;
  52. ;    foreach CurIndex in n-1..0 do
  53. ;
  54. ;        yield CurIndex;
  55. ;
  56. ;    endfor;
  57. ; end UpDown;
  58. ;
  59. ;
  60. ;
  61. ; SumToN:iterator(n:integer):integer;
  62. ; var
  63. ;    CurIndex:integer;
  64. ;    Sum:     integer;
  65. ; endvar;
  66. ; begin SumToN;
  67. ;
  68. ;    Sum := 0;
  69. ;    foreach CurIndex in 0..n do
  70. ;
  71. ;        Sum := Sum + CurIndex;
  72. ;        yield Sum;
  73. ;
  74. ;    endfor;
  75. ;
  76. ; end SumToN;
  77. ;
  78. ;
  79. ; MultiIter returns a pointer to an iterator that accepts a single integer parameter.
  80. ;
  81. ; MultiIter: iterator: [iterator(n:integer)];
  82. ; begin MultiIter;
  83. ;
  84. ;    yield @Fib;    (* Return pointers to the three iterators above *)
  85. ;    yield @UpDown;    (* as the result of this iterator.        *)
  86. ;    yield @SumToN;
  87. ;
  88. ; end MultiIter;
  89. ;
  90. ;
  91. ; var
  92. ;    i:integer;
  93. ;    n:integer;
  94. ;    iter:[iterator(n:integer)];
  95. ; endvar;
  96. ;
  97. ; begin EX12_1;
  98. ;
  99. ;    (* The following for loop repeats six times, passing its loop index as    *)
  100. ;    (* the parameter to the Fib, UpDown, and SumToN parameters.        *)
  101. ;
  102. ;    foreach n in 0..5 do
  103. ;
  104. ;
  105. ;        (* The following (funny looking) iterator sequences through    *)
  106. ;        (* each of the three iterators: Fib, UpDown, and SumToN.  It    *)
  107. ;        (* returns a pointer as the iterator value.  The innermost    *)
  108. ;        (* foreach loop uses this pointer to call the appropriate    *)
  109. ;        (* iterator.                            *)
  110. ;
  111. ;        foreach iter in MultiIter do
  112. ;
  113. ;            (* Okay, this for loop invokes whatever iterator was    *)
  114. ;            (* return by the MultiIter iterator above.        *)
  115. ;
  116. ;            foreach i in [MultiIter](n) do
  117. ;
  118. ;                write(i:3);
  119. ;
  120. ;            endfor;
  121. ;            writeln;
  122. ;
  123. ;        endfor;
  124. ;        writeln;
  125. ;
  126. ;    endfor;
  127. ;
  128. ; end EX12_1;
  129.  
  130.         .xlist
  131.         include     stdlib.a
  132.         includelib    stdlib.lib
  133.         .list
  134.  
  135.         .286                ;Allow extra adrs modes.
  136.  
  137.  
  138. wp        textequ    <word ptr>
  139.  
  140.  
  141. dseg        segment    para public 'code'
  142. dseg        ends
  143.  
  144.  
  145. cseg        segment    para public 'code'
  146.         assume    cs:cseg, ss:sseg
  147.  
  148.  
  149.  
  150.  
  151. ; The following macro builds a resume frame and the returns to the caller
  152. ; of an iterator.  It assumes that the iterator and whoever called the
  153. ; iterator have the standard activation record defined above and that we
  154. ; are building the standard resume frame described above.
  155. ;
  156. ; This code wipes out the DX register.  Whoever calls the iterator cannot
  157. ; count on DX being preserved, likewise, the iterator cannot count on DX
  158. ; being preserved across a yield.  Presumably, the iterator returns its
  159. ; value in AX.
  160.  
  161.  
  162. Yield        macro
  163.                 mov     dx, [BP+2]              ;Place to yield back to.
  164.         push    bp            ;Save Iterator link
  165.                 mov     bp, [bp]                ;Get ptr to caller's A.R.
  166.         call    dx            ;Push resume address and rtn.
  167.         pop    bp            ;Restore ptr to our A. R.
  168.         endm
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175. ; Fib(n) - Yields the sequence of fibonacci numbers from F(0)..F(n).
  176. ;       The fibonacci sequence is defined as:
  177. ;
  178. ;        F(0) and F(1) = 1.
  179. ;        F(n) = F(n-1) + F(n-2) for n > 1.
  180.  
  181.  
  182. ; The following structure defines the activation record for Fib
  183.  
  184. CurIndex    textequ    <[bp-6]>    ;Current sequence value.
  185. Fn1        textequ    <[bp-4]>    ;F(n-1) value.
  186. Fn2        textequ    <[bp-2]>    ;F(n-2) value.
  187. DynamicLink    textequ    <[bp]>        ;Saved BP value.
  188. YieldAdrs    textequ    <[bp+2]>    ;Return Adrs for proc.
  189. FailAdrs        textequ <[bp+4]>        ;Go here when we fail
  190. n               textequ <[bp+6]>        ;The initial parameter
  191.  
  192.  
  193. Fib        proc
  194.         push    bp
  195.         mov    bp, sp
  196.         sub    sp, 6        ;Make room for local variables.
  197.  
  198. ; We will also begin yielding values starting at F(0).
  199. ; Since F(0) and F(1) are special cases, yield their values here.
  200.  
  201.         mov    ax, 1        ;Yield F(0) (we always return at least
  202.         yield            ; F(0)).
  203.  
  204.         cmp    wp n, 1        ;See if user called this with n=0.
  205.         jb    FailFib
  206.                 mov     ax, 1
  207.                 yield
  208.  
  209. ; Okay, n >=1 so we need to go into a loop to handle the remaining values.
  210. ; First, begin by initializing Fn1 and Fn2 as appropriate.
  211.  
  212.                 mov     wp Fn1, 1
  213.                 mov     wp Fn2, 1
  214.                 mov     wp CurIndex, 2
  215.  
  216. WhlLp:        mov     ax, CurIndex        ;See if CurIndex > n.
  217.                 cmp     ax, n
  218.                 ja      FailFib
  219.  
  220.                 push    Fn1
  221.                 mov     ax, Fn1
  222.                 add     ax, Fn2
  223.                 pop     Fn2            ;Fn1 becomes the new Fn2 value.
  224.                 mov     Fn1, ax            ;Current value becomes new Fn1 value.
  225.                 yield                ;Yield the current value.
  226.  
  227.                 inc     wp CurIndex
  228.                 jmp     WhlLp
  229.  
  230.  
  231.  
  232. FailFib:    mov     sp, bp            ;Deallocate local vars.
  233.                 pop     bp            ;Restore Dynamic Link.
  234.                 add     sp, 2            ;Skip ret adrs.
  235.                 ret     2            ;Return through fail address.
  236. Fib        endp
  237.  
  238.  
  239.  
  240.  
  241.  
  242. ; UpDown-       This function yields the sequence 0, 1, 2, ..., n, n-1,
  243. ;               n-2, ..., 1, 0.
  244.  
  245.  
  246. i               textequ <[bp-2]>        ;F(n-2) value.
  247.  
  248. UpDown        proc
  249.         push    bp
  250.         mov    bp, sp
  251.         sub    sp, 2        ;Make room for i.
  252.  
  253.         mov    wp i, 0        ;Initialize our index variable (i).
  254. UptoN:        mov    ax, i
  255.         cmp    ax, n
  256.         jae    GoDown
  257.  
  258.         yield
  259.  
  260.         inc    wp i
  261.         jmp    UpToN
  262.  
  263.  
  264. GoDown:        mov    ax, i
  265.         yield
  266.         mov    ax, i
  267.         cmp    ax, 0
  268.         je    UpDownDone
  269.         dec    wp i
  270.         jmp    GoDown
  271.  
  272. UpDownDone:     mov     sp, bp                  ;Deallocate local vars.
  273.                 pop     bp                      ;Restore Dynamic Link.
  274.                 add     sp, 2                   ;Skip ret adrs.
  275.                 ret     2                       ;Return through fail address.
  276. UpDown        endp
  277.  
  278.  
  279.  
  280.  
  281.  
  282. ; SumToN(n)-    This iterator returns 1, 2, 3, 6, 10, ... sum(n) where
  283. ;        sum(n) = 1+2+3+4+...+n  (e.g., n(n+1)/2);
  284.  
  285. j               textequ <[bp-2]>        
  286. k        textequ    <[bp-4]>
  287.  
  288. SumToN        proc
  289.         push    bp
  290.         mov    bp, sp
  291.         sub    sp, 4        ;Make room for j and k.
  292.  
  293.         mov    wp j, 0        ;Initialize our index variable (j).
  294.         mov    wp k, 0        ;Initialize our sum (k).
  295. SumLp:        mov    ax, j
  296.         cmp    ax, n
  297.         ja    SumDone
  298.  
  299.         add    ax, k
  300.         mov    k, ax
  301.  
  302.         yield
  303.  
  304.         inc    wp j
  305.         jmp    SumLp
  306.  
  307. SumDone:    mov     sp, bp                  ;Deallocate local vars.
  308.                 pop     bp                      ;Restore Dynamic Link.
  309.                 add     sp, 2                   ;Skip ret adrs.
  310.                 ret     2                       ;Return through fail address.
  311. SumToN        endp
  312.  
  313.  
  314.  
  315.  
  316.  
  317. ; MultiIter-    This iterator returns a pointer to each of the above iterators.
  318.  
  319. MultiIter    proc
  320.         push    bp
  321.         mov    bp, sp
  322.  
  323.         mov    ax, offset Fib
  324.         yield
  325.         mov    ax, offset UpDown
  326.         yield
  327.         mov    ax, offset SumToN
  328.         yield
  329.  
  330.         pop    bp
  331.         add    sp, 2
  332.         ret
  333. MultiIter    endp
  334.  
  335.  
  336.  
  337.  
  338. Main        proc
  339.         mov    ax, dseg
  340.         mov    ds, ax
  341.         mov    es, ax
  342.  
  343.  
  344.         meminit
  345.  
  346. ; foreach bx in 0..5 do
  347.  
  348.         mov    bx, 0         ;Loop control variable for outer loop.
  349. WhlBXle5:    
  350.  
  351. ; foreach ax in MultiIter do
  352.  
  353.         push    offset MultiDone ;Failure address.
  354.         call    MultiIter     ;Get iterator to call.
  355.  
  356.  
  357. ; foreach i in [ax](bx) do
  358.  
  359.         push    bx        ;Push "n" (bx) onto the stack.
  360.         push    offset IterDone    ;Failure Address
  361.         call    ax        ;Call the iterator pointed at by the
  362. ;                    ; return value from MultiIter.
  363. ;
  364. ; write(ax:3);
  365.  
  366.         mov    cx, 3
  367.         putisize    
  368.         ret
  369.  
  370. ; endfor, writeln;
  371.  
  372. IterDone:    putcr            ;Writeln;
  373.         ret
  374.  
  375. ; endfor, writeln;
  376.  
  377. MultiDone:    putcr
  378.         inc    bx
  379.         cmp    bx, 5
  380.         jbe    WhlBXle5
  381.  
  382. ; endfor
  383.  
  384. Quit:        ExitPgm            ;DOS macro to quit program.
  385. Main        endp
  386.  
  387. cseg            ends
  388.  
  389.  
  390. sseg        segment    para stack 'stack'
  391. stk        word    1024 dup (0)
  392. sseg        ends
  393.  
  394. zzzzzzseg    segment    para public 'zzzzzz'
  395. LastBytes    db    16 dup (?)
  396. zzzzzzseg    ends
  397.         end    Main
  398.