📄 ex12_1.asm
字号:
; EX12_1.asm
;
; Program to support the laboratory exercise in Chapter 12.
;
; This program combines iterators, passing parameters as parameters,
; and procedural parameters all into the same program.
;
;
; This program implements the following iterators (examples written in panacea):
;
; program EX12_1;
;
; fib:iterator(n:integer):integer;
; var
; CurIndex:integer;
; Fn1: integer;
; Fn2: integer;
; endvar;
; begin fib;
;
; yield 1; (* Always have at least n=0 *)
; if (n <> 0) then
;
; yield 1; (* Have at least n=1 at this point *)
;
; Fn1 := 1;
; Fn2 := 1;
; foreach CurIndex in 2..n do
;
; yield Fn1+Fn2;
; Fn2 = Fn1;
; Fn1 = CurIndex;
;
; endfor;
; endif;
;
; end fib;
;
;
;
; UpDown:iterator(n:integer):integer;
; var
; CurIndex:integer;
; endvar;
; begin UpDown;
;
; foreach CurIndex in 0..n do
;
; yield CurIndex;
;
; endfor;
; foreach CurIndex in n-1..0 do
;
; yield CurIndex;
;
; endfor;
;
; end UpDown;
;
;
;
; SumToN:iterator(n:integer):integer;
; var
; CurIndex:integer;
; Sum: integer;
; endvar;
; begin SumToN;
;
; Sum := 0;
; foreach CurIndex in 0..n do
;
; Sum := Sum + CurIndex;
; yield Sum;
;
; endfor;
;
; end SumToN;
;
;
; MultiIter returns a pointer to an iterator that accepts a single integer parameter.
;
; MultiIter: iterator: [iterator(n:integer)];
; begin MultiIter;
;
; yield @Fib; (* Return pointers to the three iterators above *)
; yield @UpDown; (* as the result of this iterator. *)
; yield @SumToN;
;
; end MultiIter;
;
;
; var
; i:integer;
; n:integer;
; iter:[iterator(n:integer)];
; endvar;
;
; begin EX12_1;
;
; (* The following for loop repeats six times, passing its loop index as *)
; (* the parameter to the Fib, UpDown, and SumToN parameters. *)
;
; foreach n in 0..5 do
;
;
; (* The following (funny looking) iterator sequences through *)
; (* each of the three iterators: Fib, UpDown, and SumToN. It *)
; (* returns a pointer as the iterator value. The innermost *)
; (* foreach loop uses this pointer to call the appropriate *)
; (* iterator. *)
;
; foreach iter in MultiIter do
;
; (* Okay, this for loop invokes whatever iterator was *)
; (* return by the MultiIter iterator above. *)
;
; foreach i in [MultiIter](n) do
;
; write(i:3);
;
; endfor;
; writeln;
;
; endfor;
; writeln;
;
; endfor;
;
; end EX12_1;
.xlist
include stdlib.a
includelib stdlib.lib
.list
.286 ;Allow extra adrs modes.
wp textequ <word ptr>
dseg segment para public 'code'
dseg ends
cseg segment para public 'code'
assume cs:cseg, ss:sseg
; The following macro builds a resume frame and the returns to the caller
; of an iterator. It assumes that the iterator and whoever called the
; iterator have the standard activation record defined above and that we
; are building the standard resume frame described above.
;
; This code wipes out the DX register. Whoever calls the iterator cannot
; count on DX being preserved, likewise, the iterator cannot count on DX
; being preserved across a yield. Presumably, the iterator returns its
; value in AX.
Yield macro
mov dx, [BP+2] ;Place to yield back to.
push bp ;Save Iterator link
mov bp, [bp] ;Get ptr to caller's A.R.
call dx ;Push resume address and rtn.
pop bp ;Restore ptr to our A. R.
endm
; Fib(n) - Yields the sequence of fibonacci numbers from F(0)..F(n).
; The fibonacci sequence is defined as:
;
; F(0) and F(1) = 1.
; F(n) = F(n-1) + F(n-2) for n > 1.
; The following structure defines the activation record for Fib
CurIndex textequ <[bp-6]> ;Current sequence value.
Fn1 textequ <[bp-4]> ;F(n-1) value.
Fn2 textequ <[bp-2]> ;F(n-2) value.
DynamicLink textequ <[bp]> ;Saved BP value.
YieldAdrs textequ <[bp+2]> ;Return Adrs for proc.
FailAdrs textequ <[bp+4]> ;Go here when we fail
n textequ <[bp+6]> ;The initial parameter
Fib proc
push bp
mov bp, sp
sub sp, 6 ;Make room for local variables.
; We will also begin yielding values starting at F(0).
; Since F(0) and F(1) are special cases, yield their values here.
mov ax, 1 ;Yield F(0) (we always return at least
yield ; F(0)).
cmp wp n, 1 ;See if user called this with n=0.
jb FailFib
mov ax, 1
yield
; Okay, n >=1 so we need to go into a loop to handle the remaining values.
; First, begin by initializing Fn1 and Fn2 as appropriate.
mov wp Fn1, 1
mov wp Fn2, 1
mov wp CurIndex, 2
WhlLp: mov ax, CurIndex ;See if CurIndex > n.
cmp ax, n
ja FailFib
push Fn1
mov ax, Fn1
add ax, Fn2
pop Fn2 ;Fn1 becomes the new Fn2 value.
mov Fn1, ax ;Current value becomes new Fn1 value.
yield ;Yield the current value.
inc wp CurIndex
jmp WhlLp
FailFib: mov sp, bp ;Deallocate local vars.
pop bp ;Restore Dynamic Link.
add sp, 2 ;Skip ret adrs.
ret 2 ;Return through fail address.
Fib endp
; UpDown- This function yields the sequence 0, 1, 2, ..., n, n-1,
; n-2, ..., 1, 0.
i textequ <[bp-2]> ;F(n-2) value.
UpDown proc
push bp
mov bp, sp
sub sp, 2 ;Make room for i.
mov wp i, 0 ;Initialize our index variable (i).
UptoN: mov ax, i
cmp ax, n
jae GoDown
yield
inc wp i
jmp UpToN
GoDown: mov ax, i
yield
mov ax, i
cmp ax, 0
je UpDownDone
dec wp i
jmp GoDown
UpDownDone: mov sp, bp ;Deallocate local vars.
pop bp ;Restore Dynamic Link.
add sp, 2 ;Skip ret adrs.
ret 2 ;Return through fail address.
UpDown endp
; SumToN(n)- This iterator returns 1, 2, 3, 6, 10, ... sum(n) where
; sum(n) = 1+2+3+4+...+n (e.g., n(n+1)/2);
j textequ <[bp-2]>
k textequ <[bp-4]>
SumToN proc
push bp
mov bp, sp
sub sp, 4 ;Make room for j and k.
mov wp j, 0 ;Initialize our index variable (j).
mov wp k, 0 ;Initialize our sum (k).
SumLp: mov ax, j
cmp ax, n
ja SumDone
add ax, k
mov k, ax
yield
inc wp j
jmp SumLp
SumDone: mov sp, bp ;Deallocate local vars.
pop bp ;Restore Dynamic Link.
add sp, 2 ;Skip ret adrs.
ret 2 ;Return through fail address.
SumToN endp
; MultiIter- This iterator returns a pointer to each of the above iterators.
MultiIter proc
push bp
mov bp, sp
mov ax, offset Fib
yield
mov ax, offset UpDown
yield
mov ax, offset SumToN
yield
pop bp
add sp, 2
ret
MultiIter endp
Main proc
mov ax, dseg
mov ds, ax
mov es, ax
meminit
; foreach bx in 0..5 do
mov bx, 0 ;Loop control variable for outer loop.
WhlBXle5:
; foreach ax in MultiIter do
push offset MultiDone ;Failure address.
call MultiIter ;Get iterator to call.
; foreach i in [ax](bx) do
push bx ;Push "n" (bx) onto the stack.
push offset IterDone ;Failure Address
call ax ;Call the iterator pointed at by the
; ; return value from MultiIter.
;
; write(ax:3);
mov cx, 3
putisize
ret
; endfor, writeln;
IterDone: putcr ;Writeln;
ret
; endfor, writeln;
MultiDone: putcr
inc bx
cmp bx, 5
jbe WhlBXle5
; endfor
Quit: ExitPgm ;DOS macro to quit program.
Main endp
cseg ends
sseg segment para stack 'stack'
stk word 1024 dup (0)
sseg ends
zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
zzzzzzseg ends
end Main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -