CSC258H: Week 9 Reading Guide

Week 9: Functions, System Calls, and Exceptions

This is important. A couple of brave students dropped in last week to talk to me about their troubles with the class and, in particular, with the readings. Together, we discovered that several of them were attempting to read cover to cover -- from the first word in the assigned readings to the end. That's probably not going to work. It's not how I read technical material. Instead, please try to read with a purpose. The exercises can help provide a purpose. This guide can, too.

First, scan this reading guide and look for any definitions you've been asked to find. Find those words and highlight (or save) the definitions. Next, skim the section looking for answers to the questions posed in the guide. (Examples and figures can be a tremendous help. Mark particularly useful examples as you find them, so you can find them again quickly.) If you read a piece of text, make sure you have a particular question you're trying to answer in mind, and skip sections of text that don't address that question.

Finally, get to the actual work for most weeks (but less so this week): flip to the recommended exercises and start working on them, one by one. For each exercise, find the example or passage in the text that is most related and read that text with the goal of learning what you need to solve the problem. Move back and forth between the problem and the text, using the book as a reference. If you get stuck, write down a question for lecture or office hours or, if you are comfortable, post it on the discussion board, and then move on.

Okay, back to the regularly scheduled (not-)readings ...

Topic Reading Recommended Exercises
Functions DDCA 6.4.6
and, optionally, Larus's A.6
Exercises 6.17, 6.18, 6.21
For extra practice: Exercises 6.15 and 6.16 (especially after the week 10 lab)
The Compiler Tool Chain DDCA 6.5-6.6 None: See reading guide questions
System Calls and Exceptions DDCA 6.7.2
and Larus's A.7
None: see reading guide questions

This week, we're looking at the impact of function calls on the architecture. To do that, we need to understand that the process for invoking a function is a convention -- a set of agreements that the code calling a function and the code implementing the function agree upon. We'll study that convention (in 6.4.6), look at how tool support uses those conventions to combine pieces of code (6.6), and examine how function calls differ from system calls (6.7.2). In class, we'll examine our own expectations, as programmers, of function calls and look at how they're implemented in the convention.

Also, just for information: the labs will start lagging behind the reading a bit, because of the reordering we did last week. The lab for function calls won't occur until the week after the lecture, and the lab focusing on system call mechanisms won't happen until the end of the term.

Functions: Section 6.4.6

Functions allow us to modularize our code and to collaboratively build programs. However, in any such environment, we need rules to make sure that the systems we build can work together -- so functions are just collections of agreements (conventions). Those conventions utilize a small set of mechanisms that make functions possible. Find these mechanisms and make sure you understand their role: the jump-and-link instruction and return address ($ra), argument registers ($a0-$a3), return value register ($v0, $v1), stack (including the stack pointer (SP) register), and caller and callee save registers.

The recursive function example (6.27) is a good test of your understanding of the conventions from the book.

Larus's assembly guide provides an alternate look on the same mechanisms, if you would like an alternate text. The examples in that guide are helpful, but note that Larus does not use exactly the same conventions as our textbook! (Can you spot the differences?) That's perfectly fine: function call conventions are just that -- agreements. As tool developers, we just have to be sure that the conventions we adhere to match the expectations of the toolchain we work with.

The Compiler Tool Chain: Sections 6.5-6.6

Section 6.5 isn't actually about the tool chain, but it provides some background on how branch addresses are calculated, and those might be details you want to understand how the linker in the next section works.

The address space diagram (Figure 6.31) should already be familiar, so the new material is primarily in Section 6.6.2. Figure 6.32 provides a good overview of the material being presented and is a chart you may wish to know in detail. (What are the names of the tools in the compiler toolchain? What are the inputs and outputs of each stage?) There aren't any exercises in the text for this section. Instead, here are some questions to answer: what is the responsibility of each compilation stage?, what does the linker let us do, as programmers?, and why does the assembler take multiple passes? And here is a challenge question for those of you in CSC209: what structures and/or extra information does gcc's -g flag cause to be saved in the executable? (If you're not in CSC209: what additional information does a debugger need to allow you to set breakpoints and to query the value of variables?)

System Calls and Exceptions: Section 6.7.2 (and Larus's A.7)

System calls may look like functions, but they have to take a different path because they are requests to perform potentially dangerous operations. (Dangerous in this context means "Could impact another running program.") To do this work, we invoke the operating system to perform the work for us, and the operating system must run in a privileged mode (a mode with no restrictions on the operations to be performed). To enter privileged mode, we need to invoke an exception. The same mechanism is used to deal with errors. When you see the dreaded "Segmentation Fault," your processor raised an exception that was interpreted by the operating system.

Our textbook provides a very good high-level view of how exceptions work, but to get a deeper understanding of what occurs to enter and exit an exception, you can look at the example exception handler in Larus's A.7. (That exception handler doesn't actually do anything useful to handle the exception; it's just an example of how to enter the exception, identify the cause, and exit.) The example is also a good test of your assembly reading skills: at each instruction, do you know why the instruction is necessary? (You can't omit a single instruction without having the handler fail.) Some other key questions to consider, in lieu of exercises: What does the Cause register tell us? How does the handler avoid destroying registers used by the user program? Why do we have to worry about exceptions occurring while we are handling an exception? How does the exception return to the point in the user's code where it was invoked? And here is one subtle question: Why is the exception handler at a specific location in memory?