Working on 5.11
parent
8a2ce473be
commit
5b7e799f2f
|
@ -210,10 +210,10 @@
|
|||
(goto (label fib-loop)) ; perform recursive call
|
||||
afterfib-n-1 ; upon return, val contains Fib(n - 1)
|
||||
(restore n)
|
||||
;(restore continue)
|
||||
;(restore continue) ; uneeded restore
|
||||
;; set up to compute Fib(n - 2)
|
||||
(assign n (op -) (reg n) (const 2))
|
||||
;(save continue)
|
||||
;(save continue) ; uneeded continue
|
||||
(assign continue (label afterfib-n-2))
|
||||
(save val) ; save Fib(n - 1)
|
||||
(goto (label fib-loop))
|
||||
|
|
|
@ -103,38 +103,84 @@
|
|||
(start triple-inc-machine)
|
||||
(assert (get-register-contents triple-inc-machine 'a) 11)
|
||||
|
||||
(display "\nex-5.11\n")
|
||||
(display "\nex-5.11 - stack-behavior\n")
|
||||
|
||||
;Exercise 5.11. When we introduced save and restore in section 5.1.4, we
|
||||
;didn't specify what would happen if you tried to restore a register that was
|
||||
;not the last one saved, as in the sequence
|
||||
; a
|
||||
(define fib-machine
|
||||
(make-machine
|
||||
'(n val continue)
|
||||
(list (list '< <) (list '- -) (list '= +) (list '+ +))
|
||||
'(controller
|
||||
(assign continue (label fib-done))
|
||||
fib-loop
|
||||
(test (op <) (reg n) (const 2))
|
||||
(branch (label immediate-answer))
|
||||
;; set up to compute Fib(n - 1)
|
||||
(save continue)
|
||||
(assign continue (label afterfib-n-1))
|
||||
(save n) ; save old value of n
|
||||
(assign n (op -) (reg n) (const 1)); clobber n to n - 1
|
||||
(goto (label fib-loop)) ; perform recursive call
|
||||
afterfib-n-1 ; upon return, val contains Fib(n - 1)
|
||||
(restore n)
|
||||
;; set up to compute Fib(n - 2)
|
||||
(assign n (op -) (reg n) (const 2))
|
||||
(assign continue (label afterfib-n-2))
|
||||
(save val) ; save Fib(n - 1)
|
||||
(goto (label fib-loop))
|
||||
afterfib-n-2 ; upon return, val contains Fib(n - 2)
|
||||
; (assign n (reg val)) ; n now contains Fib(n - 2)
|
||||
; (restore val) ; val now contains Fib(n - 1)
|
||||
(restore n) ; ex-5.11 - save one instruction
|
||||
(assign val ; Fib(n - 1) + Fib(n - 2)
|
||||
(op +) (reg val) (reg n))
|
||||
(restore continue)
|
||||
(goto (reg continue)) ; return to caller, answer is in val
|
||||
immediate-answer
|
||||
(assign val (reg n)) ; base case: Fib(n) = n
|
||||
(goto (reg continue))
|
||||
fib-done)))
|
||||
|
||||
;(save y)
|
||||
;(save x)
|
||||
;(restore y)
|
||||
; We can replace ((assign n (reg val)) (restore val)) with (restore n) because
|
||||
; we add up n and val anyway. It does not matter which is in which register.
|
||||
|
||||
;There are several reasonable possibilities for the meaning of restore:
|
||||
(set-register-contents! fib-machine 'n 8)
|
||||
(start fib-machine)
|
||||
(display "a. ")
|
||||
(assert (get-register-contents fib-machine 'val) 21)
|
||||
|
||||
;a. (restore y) puts into y the last value saved on the stack, regardless of
|
||||
;what register that value came from. This is the way our simulator behaves.
|
||||
;Show how to take advantage of this behavior to eliminate one instruction from
|
||||
;the Fibonacci machine of section 5.1.4 (figure 5.12).
|
||||
; b.
|
||||
(define stack-content car)
|
||||
(define stack-register cadr)
|
||||
|
||||
;b. (restore y) puts into y the last value saved on the stack, but only if
|
||||
;that value was saved from y; otherwise, it signals an error. Modify the
|
||||
;simulator to behave this way. You will have to change save to put the register
|
||||
;name on the stack along with the value.
|
||||
(define (make-save inst machine stack pc)
|
||||
(let ((reg (get-register machine
|
||||
(stack-inst-reg-name inst))))
|
||||
(lambda ()
|
||||
(push stack (list (get-contents reg) reg))
|
||||
(advance-pc pc))))
|
||||
|
||||
(define (make-restore inst machine stack pc)
|
||||
(let ((reg (get-register machine
|
||||
(stack-inst-reg-name inst))))
|
||||
(lambda ()
|
||||
(let ((stack-element (pop stack)))
|
||||
(if (not (eq? reg (stack-register stack-element)))
|
||||
(error "restore from different reg -- MAKE-RESTORE"
|
||||
(reg 'name?)
|
||||
((stack-register stack-element) 'name?)))
|
||||
(set-contents! reg (stack-content stack-element))
|
||||
(advance-pc pc)))))
|
||||
|
||||
(display "b. [implemented]\n")
|
||||
|
||||
(display "c. ACTIVE!!!\n")
|
||||
;c. (restore y) puts into y the last value saved from y regardless of what
|
||||
;other registers were saved after y and not restored. Modify the simulator to
|
||||
;behave this way. You will have to associate a separate stack with each
|
||||
;register. You should make the initialize-stack operation initialize all the
|
||||
;register stacks.
|
||||
|
||||
; Extend the message-passing interface to the machine to provide access to
|
||||
; this new information. To test your analyzer, define the Fibonacci machine
|
||||
; from figure 5.12 and examine the lists you constructed.
|
||||
|
||||
(display "\nex-5.12\n")
|
||||
|
||||
; (display "\nex-5.13\n")
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
(cond ((eq? message 'get) contents)
|
||||
((eq? message 'set)
|
||||
(lambda (value) (set! contents value)))
|
||||
((eq? message 'name?) name)
|
||||
(else
|
||||
(error "Unknown request -- REGISTER" message))))
|
||||
dispatch))
|
||||
|
|
Loading…
Reference in New Issue