1 00:00:01,040 --> 00:00:05,850 Let's practice our newfound skill and see what we can determine about a running program 2 00:00:05,850 --> 00:00:09,710 which we've stopped somewhere in the middle of its execution. 3 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 4 00:00:15,160 --> 00:00:17,970 to be executed is 0x40. 5 00:00:17,970 --> 00:00:21,820 We're also given the stack dump shown on right. 6 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 7 00:00:26,700 --> 00:00:30,579 others) is an activation record for the fact function. 8 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 9 00:00:35,870 --> 00:00:40,450 generate the annotations shown on the right of the stack dump. 10 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 11 00:00:45,990 --> 00:00:48,870 value 3. 12 00:00:48,870 --> 00:00:53,460 Now we want to know the argument to original call to fact. 13 00:00:53,460 --> 00:00:57,960 We'll have to label the other stack frames using the saved BP values. 14 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 15 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 16 00:01:09,930 --> 00:01:13,789 address for the recursive fact calls. 17 00:01:13,789 --> 00:01:19,050 Looking through the stack frames we find the first return address that's *not* 0x40, which 18 00:01:19,050 --> 00:01:23,950 must an return address to code that's not part of the fact procedure. 19 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 20 00:01:29,229 --> 00:01:32,470 argument to the original call is 6. 21 00:01:32,470 --> 00:01:37,229 What's the location of the BR that made the original call? 22 00:01:37,229 --> 00:01:43,300 Well, the saved LP in the stack frame of the original call to fact is 0x80. 23 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 24 00:01:49,400 --> 00:01:54,830 original call is one instruction earlier, at location 0x7C. 25 00:01:54,830 --> 00:01:59,830 To answer these questions you have to be good at hex arithmetic! 26 00:01:59,830 --> 00:02:03,200 What instruction is about to be executed? 27 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 28 00:02:09,529 --> 00:02:10,908 fact calls. 29 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 30 00:02:17,029 --> 00:02:18,549 fact code. 31 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. 32 00:02:25,650 --> 00:02:27,769 What value is in BP? 33 00:02:27,769 --> 00:02:29,159 Hmm. 34 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 35 00:02:34,989 --> 00:02:36,918 stack frame. 36 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 37 00:02:42,219 --> 00:02:44,930 in the *previous* stack frame. 38 00:02:44,930 --> 00:02:49,969 So the saved BP value gives us the address of a particular stack location, from which 39 00:02:49,969 --> 00:02:53,829 we can derive the address of all the other locations! 40 00:02:53,829 --> 00:03:00,689 Counting forward, we find that the value in BP must be 0x13C. 41 00:03:00,689 --> 00:03:03,610 What value is in SP? 42 00:03:03,610 --> 00:03:07,870 Since we're about to execute the DEALLOCATE to remove the argument of the nested call 43 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. 44 00:03:13,959 --> 00:03:19,420 Since the SP points to first unused stack location, it points to the location after 45 00:03:19,420 --> 00:03:23,829 that word, so it has the value 0x144. 46 00:03:23,829 --> 00:03:28,519 Finally, what value is in R0? 47 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 48 00:03:34,090 --> 00:03:36,400 recursive call, which is 2. 49 00:03:36,400 --> 00:03:37,400 Wow! 50 00:03:37,400 --> 00:03:43,200 You can learn a lot from the stacked activation records and a little deduction! 51 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 52 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 53 00:03:54,379 --> 00:03:55,709 up to. 54 00:03:55,709 --> 00:03:57,799 Pretty neat… 55 00:03:57,799 --> 00:04:02,680 Wrapping up, we've been dedicating some registers to help with our various software conventions. 56 00:04:02,680 --> 00:04:08,549 To summarize: R31 is always zero, as defined by the ISA. 57 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 58 00:04:15,079 --> 00:04:17,170 of the Beta in the next lecture. 59 00:04:17,170 --> 00:04:20,488 Meanwhile, don't use R30 in your code! 60 00:04:20,488 --> 00:04:26,200 The remaining dedicated registers are connected with our software conventions: 61 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 62 00:04:35,310 --> 00:04:40,180 R27 (BP) is used as the base pointer. 63 00:04:40,180 --> 00:04:43,950 As you practice reading and writing code, you'll grow familiar with these dedicated 64 00:04:43,950 --> 00:04:47,380 registers. 65 00:04:47,380 --> 00:04:52,760 In thinking about how to implement procedures, we discovered the need for an activation record 66 00:04:52,760 --> 00:04:57,350 to store the information needed by any active procedure call. 67 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. 68 00:05:03,150 --> 00:05:07,530 And the record can be discarded when the procedure is complete. 69 00:05:07,530 --> 00:05:13,620 The activation records hold argument values, saved LP and BP values along with the caller's 70 00:05:13,620 --> 00:05:17,830 values in any other of the registers. 71 00:05:17,830 --> 00:05:23,700 Storage for the procedure's local variables is also allocated in the activation record. 72 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 73 00:05:28,780 --> 00:05:32,400 arguments and local variables. 74 00:05:32,400 --> 00:05:37,940 We adopted a "callee saves" convention where the called procedure is obligated to preserve 75 00:05:37,940 --> 00:05:42,520 the values in all registers except for R0. 76 00:05:42,520 --> 00:05:46,780 Taken together, these conventions allow us to have procedures with arbitrary numbers 77 00:05:46,780 --> 00:05:51,700 of arguments and local variables, with nested and recursive procedure calls. 78 00:05:51,700 --> 00:05:55,840 We're now ready to compile and execute any C program!