WEBVTT

00:00:01.040 --> 00:00:05.850
Let's practice our newfound skill and see
what we can determine about a running program

00:00:05.850 --> 00:00:09.710
which we've stopped somewhere in the middle
of its execution.

00:00:09.710 --> 00:00:15.160
We're told that a computation of fact() is
in progress and that the PC of the next instruction

00:00:15.160 --> 00:00:17.970
to be executed is 0x40.

00:00:17.970 --> 00:00:21.820
We're also given the stack dump shown on right.

00:00:21.820 --> 00:00:26.700
Since we're in the middle of a fact computation,
we know that current stack frame (and possibly

00:00:26.700 --> 00:00:30.579
others) is an activation record for the fact
function.

00:00:30.579 --> 00:00:35.870
Using the code on the previous slide we can
determine the layout of the stack frame and

00:00:35.870 --> 00:00:40.450
generate the annotations shown on the right
of the stack dump.

00:00:40.450 --> 00:00:45.990
With the annotations, it's easy to see that
the argument to current active call is the

00:00:45.990 --> 00:00:48.870
value 3.

00:00:48.870 --> 00:00:53.460
Now we want to know the argument to original
call to fact.

00:00:53.460 --> 00:00:57.960
We'll have to label the other stack frames
using the saved BP values.

00:00:57.960 --> 00:01:04.000
Looking at the saved LP values for each frame
(always found at an offset of -8 from the

00:01:04.000 --> 00:01:09.930
frame's BP), we see that many of the saved
values are 0x40, which must be the return

00:01:09.930 --> 00:01:13.789
address for the recursive fact calls.

00:01:13.789 --> 00:01:19.050
Looking through the stack frames we find the
first return address that's *not* 0x40, which

00:01:19.050 --> 00:01:23.950
must an return address to code that's not
part of the fact procedure.

00:01:23.950 --> 00:01:29.229
This means we've found the stack frame created
by the original call to fact and can see that

00:01:29.229 --> 00:01:32.470
argument to the original call is 6.

00:01:32.470 --> 00:01:37.229
What's the location of the BR that made the
original call?

00:01:37.229 --> 00:01:43.300
Well, the saved LP in the stack frame of the
original call to fact is 0x80.

00:01:43.300 --> 00:01:49.400
That's the address of the instruction following
the original call, so the BR that made the

00:01:49.400 --> 00:01:54.830
original call is one instruction earlier,
at location 0x7C.

00:01:54.830 --> 00:01:59.830
To answer these questions you have to be good
at hex arithmetic!

00:01:59.830 --> 00:02:03.200
What instruction is about to be executed?

00:02:03.200 --> 00:02:09.529
We were told its address is 0x40, which we
notice is the saved LP value for all the recursive

00:02:09.529 --> 00:02:10.908
fact calls.

00:02:10.908 --> 00:02:17.029
So 0x40 must be the address of the instruction
following the BR(fact,LP) instruction in the

00:02:17.029 --> 00:02:18.549
fact code.

00:02:18.549 --> 00:02:25.650
Looking back a few slides at the fact code,
we see that's a DEALLOCATE(1) instruction.

00:02:25.650 --> 00:02:27.769
What value is in BP?

00:02:27.769 --> 00:02:29.159
Hmm.

00:02:29.159 --> 00:02:34.989
We know BP is the address of the stack location
containing the saved R1 value in the current

00:02:34.989 --> 00:02:36.918
stack frame.

00:02:36.918 --> 00:02:42.219
So the saved BP value in the current stack
frame is the address of the saved R1 value

00:02:42.219 --> 00:02:44.930
in the *previous* stack frame.

00:02:44.930 --> 00:02:49.969
So the saved BP value gives us the address
of a particular stack location, from which

00:02:49.969 --> 00:02:53.829
we can derive the address of all the other
locations!

00:02:53.829 --> 00:03:00.689
Counting forward, we find that the value in
BP must be 0x13C.

00:03:00.689 --> 00:03:03.610
What value is in SP?

00:03:03.610 --> 00:03:07.870
Since we're about to execute the DEALLOCATE
to remove the argument of the nested call

00:03:07.870 --> 00:03:13.959
from the stack, that argument must still be
on the stack right after the saved R1 value.

00:03:13.959 --> 00:03:19.420
Since the SP points to first unused stack
location, it points to the location after

00:03:19.420 --> 00:03:23.829
that word, so it has the value 0x144.

00:03:23.829 --> 00:03:28.519
Finally, what value is in R0?

00:03:28.519 --> 00:03:34.090
Since we've just returned from a call to fact(2)
the value in R0 must the result from that

00:03:34.090 --> 00:03:36.400
recursive call, which is 2.

00:03:36.400 --> 00:03:37.400
Wow!

00:03:37.400 --> 00:03:43.200
You can learn a lot from the stacked activation
records and a little deduction!

00:03:43.200 --> 00:03:48.940
Since the state of the computation is represented
by the values of the PC, the registers, and

00:03:48.940 --> 00:03:54.379
main memory, once we're given that information
we can tell exactly what the program has been

00:03:54.379 --> 00:03:55.709
up to.

00:03:55.709 --> 00:03:57.799
Pretty neat…

00:03:57.799 --> 00:04:02.680
Wrapping up, we've been dedicating some registers
to help with our various software conventions.

00:04:02.680 --> 00:04:08.549
To summarize:
R31 is always zero, as defined by the ISA.

00:04:08.549 --> 00:04:15.079
We'll also dedicate R30 to a particular function
in the ISA when we discuss the implementation

00:04:15.079 --> 00:04:17.170
of the Beta in the next lecture.

00:04:17.170 --> 00:04:20.488
Meanwhile, don't use R30 in your code!

00:04:20.488 --> 00:04:26.200
The remaining dedicated registers are connected
with our software conventions:

00:04:26.200 --> 00:04:35.310
R29 (SP) is used as the stack pointer,
R28 (LP) is used as the linkage pointer, and

00:04:35.310 --> 00:04:40.180
R27 (BP) is used as the base pointer.

00:04:40.180 --> 00:04:43.950
As you practice reading and writing code,
you'll grow familiar with these dedicated

00:04:43.950 --> 00:04:47.380
registers.

00:04:47.380 --> 00:04:52.760
In thinking about how to implement procedures,
we discovered the need for an activation record

00:04:52.760 --> 00:04:57.350
to store the information needed by any active
procedure call.

00:04:57.350 --> 00:05:03.150
An activation record is created by the caller
and callee at the start of a procedure call.

00:05:03.150 --> 00:05:07.530
And the record can be discarded when the procedure
is complete.

00:05:07.530 --> 00:05:13.620
The activation records hold argument values,
saved LP and BP values along with the caller's

00:05:13.620 --> 00:05:17.830
values in any other of the registers.

00:05:17.830 --> 00:05:23.700
Storage for the procedure's local variables
is also allocated in the activation record.

00:05:23.700 --> 00:05:28.780
We use BP to point to the current activation
record, giving easy access the values of the

00:05:28.780 --> 00:05:32.400
arguments and local variables.

00:05:32.400 --> 00:05:37.940
We adopted a "callee saves" convention where
the called procedure is obligated to preserve

00:05:37.940 --> 00:05:42.520
the values in all registers except for R0.

00:05:42.520 --> 00:05:46.780
Taken together, these conventions allow us
to have procedures with arbitrary numbers

00:05:46.780 --> 00:05:51.700
of arguments and local variables, with nested
and recursive procedure calls.

00:05:51.700 --> 00:05:55.840
We're now ready to compile and execute any
C program!