Answer to Question 1 -- 10 points

The program starts running and sets stack variable i to 100. It next makes the system call write(). The arguments are put into registers 4, 5, and 6, and control is passed via an interrupt to the operating system. The operating system identifies the system call as a write(), extracts the arguments from the registers, and stores the values of the rest of the registers into an array. It performs error checking first, and discovers that the file descriptor, 100, is too big. It sets the variable errno in the user's address space to reflect the error (EBADF), and returns -1 to the user. This is not done with a regular return statement. Instead, register 2 is set to be -1, the PC register is set to have its old value plus four, so that it will execute the next statement in the user's code, and the rest of the registers are set to their saved values. At the point of resetting the registers, the user program regains control.

Next, the program sets the pointer ip to a million locations past that of i. Since i is a stack variable, this is going to be an address that is too high. Dereferencing it will result in a segmentation violation.

However, it is not dereferenced yet. First, write() is called again, this time with a legal file descriptor. The operating system again gets control and saves the registers. Before it attempts to perform the write(), it checks its second address to see if it is a legal user address, and it is not, so it will return -1 to the user and set errno() to EFAULT.

The user's code once again gets control and tries to dereference ip. This will cause a segmentation violation, which is a hardware interrupt. The operating system will get contol and identify the interrupt. At this point, it will terminate the user's process. The sprintf() and subsequent write() statements will not be executed.

In a real Unix implementation, it will check to see if the user desires to handle the interrupt with a previous signal() call, and if so, it passes control to that call. If not, it dumps core by writing the memory of the program to a file called core and then terminates the process.