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 #1L4: ; 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 partL5: ; 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 L7L6: ; 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 L7L7:; 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 RETL1: ; 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