Translating Functions


 

br L1
L2:
; begin of function factorial
; finish activation record for factorial's local variables
; notice that factorial has no local variables, however your compiler may
; still output a line similar to
  add sp #0 sp
  ;if n = 0
    ; the following code is intended to compare n with 0 and leave either
    ; true (1) or false (0) on the stack; since there are no direct machine
    ; language instructions that will do this for us, we have to generate
    ; a bunch of code to compute the proper value
    ; push n
      push 0(D1)
    ; push 0
      push #0
    ; compare top two stack elements for equality
    ; branch to L3 to handle the true case and drop through to handle the false case
      beq -1(SP) -2(SP) L3
    ; if not equal, pop top two stack elements and push false (0)
      sub sp #2 sp
      push #0
      br L4
      L3:
    ; if equal, pop top two stack elements and push true (1)
      sub sp #2 sp
      push #1
      L4:
    ; there is now either a true (1) or false (0) on the stack as a result of
    ; the computation of n = 0.  The following code is generated to determine
    ; whether the stack top is true or false by comparing it with 1 and branching
    ; appropriately to the then or else part of the translated if statement
      push #1
      beq -1(SP) -2(SP) L5 ; branch on true to the then part
      br L6  ;else         ; branch on false to the else part
      L5:
    ; then
      sub sp #2 sp ; remove the two values on the stack used to compare for true or false
    ; store 1 into fred's return value location
      push #1
      pop -2(D1)
    ; end of the then part, so jump to end if
      br L7
      L6:
    ; else
      sub sp #2 sp ; remove the two values on the stack used to compare for true or false
    ; push n
      push 0(D1)
    ; set up the first part of the activation record for this call to factorial
      add sp #1 sp ; leave room for return value
      push D1      ; store old D1
    ; the following is code to compute the expression n-1, which is the actual parameter
    ; to be sent on this call to factorial(n-1) and leave this value in factorial's formal
    ; parameter location for n
      push 0(D1)
      push #1
      subs
    ; at this point it is finally safe to set the place the proper value into D! so that
    ; D1 points to the new activation record being built for this call to factorial; until
    ; now, D1 had to be used in order to access variables in the *current* activation record
    ; for factorial in order to transfer actual parameters to formal parameter locations
    sub sp #1 d1
    ; the call can finally be made to factorial; remember that this pushes the current PC
    call L2
    ; this is the point of return from factorial, so the last part of the AR for that call
    ; to factorial must be removed, leaving the return value on the stack top
    ; first remove the actual parameter sent
      sub sp #1 sp
    ; now pop the old D1 value from the stack so that D1 now points to the proper AR
      pop D1
    ; the return value is now on the stack top, so the multiply
    ; n * factorial(n-1) can now be performed, since the return value is the
    ; computation of factorial(n-1)
      muls
    ; the result of the multiplication is to be assigned to factorial as a result of the
    ; execution of the line factorial := n * factorial(n-1).  This just means that the result
    ; on top of the stack should go into the return value location for factorial in this AR
      pop -2(D1) ; pop into factorial's return value location
    ; end of the else  part, so jump to endif
      br L7
      L7:
    ; end if
    ; end of factorial; remove top part of AR and return
      sub sp #0 sp ; remove local variables
    ; return to the calling routine -- remember that execution of the RET instruction
    ; pops the current top of stack into the PC, so the top stack value must be the
    ; return value that was pushed on at the pont of call
      RET
  L1:
  ; begin main
  ; set up main's activation record
    push D0
    mov sp d0
    add sp #1 sp
  ; read(n)
    rd 0(D0)
  ; writeln(n)
    wrt 0(D0)
  ; begin call to factorial by setting up the first part of factorial's  activation record and
  ; pushing actual parameter n
  ; leave room first for the return value
    add SP #1 SP
  ; then save the old D1 value
    push D1
  ; push n's value onto the stack as the first actual parameter (mode in)
    push 0(D0)
  ; finally set D1 to point to the start of this new AR
    sub SP #1 D1
  ; call factorial -- remember that execution of this call instruction pushes the PC onto the
  ; stack, which means that the address of the wrt0(D0) instruction just below the call
  ; instruction is placed onto the stack
    call L2
  ; this is the point of return from fred, so we need to remove the rest of fred's
  ; activation record by moving the sp down two, past formal parameters a and b.
    sub sp #1 sp
  ; restore the old D1 value
    pop D1
    wrts
  ; remove main's activation record
    sub sp #1 sp
    pop D0
  ; halt
    hlt