CSE 378 Homework 3

Due: Wednesday 4/23/02

Purpose

The purpose of this homework is to familiarize yourself with the Cebollita toolset. In particular, you'll be learning about the assembler, linker, and simulator provided by the toolset. You'll learn how to use the assembler and linker to build executables, and then use the simulator to run/debug them. You will also try your hand at a little assembly programming by making minor modifications to a program we provide. Finally, you'll use the Cebollita compiler to write/modify your first C-- program.

Introduction

For this assignment we'll use the following program, which computes the factorial of 9. The line numbers you see are for reference only, and are not part of the actual assembly program.
 1  # compute the factorial of 9 using the following algorithm
 2  #   N = 9
 3  #   result = 1
 4  #   while (N != 0) {
 5  #     result = result * N
 6  #     N = N - 1
 7  #   }
 8
 9  .data                                   # begin data section
10  msg:    .asciiz  "The factorial is: "   # message string
11
12  .text                           # begin program text
13  __start:
14          addi    $sp, $sp, -4            # make some space on the stack
15          addi    $t0, $0, 1              # $t0 will hold result, initially 1
16          addi    $t1, $0, 9              # $t1 will hold N, initially 9
17  top:    beq     $t1, $0, bottom
18          mult    $t0, $t0, $t1           # result = result * N
19          addi    $t1, $t1, -1            # decrement N
20          j       top                     # goto top
21  bottom:
22          sw      $t0, 0($sp)             # we'd better save result
23          addi    $v0, $0, 4              # finished w/ loop, now print out
24          addi    $a0, $gp, msg           # message, by invoking syscall 4
25          syscall                         # (print_string)
26
27          addi    $v0, $0, 1              # now print out result, by 
28          lw      $a0, 0($sp)             # invoking syscall 1 (print_int)
29          syscall
30
31          addi    $sp, $sp, 4             # reset the stack
32          addi    $v0, $0, 10             # exit syscall
33          syscall
Thankfully, you don't have to type the program in yourself, as you can download it here. Simply download this file to your home directory and use it. Make sure it's called fact.s (not fact.s.txt, as Windows will happily try to name it).

Assembling/Linking Your Program

Currently, the Cebollita tools only run on the NT machines in the lab. Eventually, you ought to be able to run these on Windows machines at home, or even on UNIX machines. In the lab, you'll need to build an executable out of the provided program. This means:
  1. Start a BASH shell on one of the lab NT machines. Do this by going to o:\cse\courses\cse378\cygwin and double-clicking "Cygwin.bat". If all goes well, you'll have a UNIX like command prompt. Most of your UNIX skills should be applicable at this command prompt.
  2. Assemble the program. In your Cygwin window, change to your work (home?) directory (where you put fact.s). Then, at the prompt type: java asm.parser fact.s
  3. If this step was successful, you should find a file called fact.o in your directory. (You can type ls to find out.)
  4. Link the program. Now type java asm.Linker fact.o. This should create a file called a.out.
These are the basic steps you'll always need to assemble/link a program. Learn them and love them. (Linking seems excessive now because there are no other object files, but the Linker still has to get involved because it resolves intra-file labels as well.)

Other useful tools are the object-file inspector and executable inspector. Typing java asm.Module fact.o should dump interesting information about the object file. Typing java util.Exe a.out should dump interesting information about the executable.

Using the Simulator: Instructions and Questions

  1. You'll first want to read over the document, Cebollita MIPS Simulator.

  2. Start the simulator (java sim.UI a.out ought to do it), and run it by single-stepping through it.
  3. Complete the following table by examining various registers and memory location contents after the appropriate instructions are executed. Using the breakpoint command may help in certain situations.

    Location Line 16 Line 19
    3rd iteration
    Line 19
    5th iteration
    Line 19
    8th iteration
    Line 24
    $t0




    $t1




    0($sp)




  4. In total, how many instructions (in the simulator) are executed to calculate the factorial of 9? The right way to answer this question is not to step the program through 9 loops and count instructions, but rather determine how many instructions are exectuted before the loop, during one iteration of the loop, and after the loop. Then you can give us an answer in terms of N, where N is the value we're calculating the factorial of (as well as the number of times the loop iterates).
     
    
    
    

Assembly Programming: Modifications

Modify the given code so that it reads a value of N from the user, and then computes its factorial. Do this by reading the simulator user's manual (above), as well as Appendix A, to figure out how to make the appropriate syscall. Next, modify the program to continue prompting the user for values of N and computing their factorials. Exit the program when the user enters a negative number. You'll need to re-assemble and re-link your program each time you make modifications. Remember, there is no "development environment" here to do this for you.

Compilers

The Cebollita toolkit provides a compiler that compiles a subset of the C language (we call it C--). Below is the C-- version of the factorial program. It can be found here. Copy the program to your home directory; compile and run the program using the simulator:
  1. Compile: java comp.parser hw3.c. This will create a file called hw3.s.
  2. Now assemble hw3.s (as above).
  3. Linking is a little trickier, because this file makes references to printInt(), printString() and exit(), which are simple functions that wrap up the associated system calls. (If we try to link at this point, with java asm.Linker hw3.o, we'll get an error. Try it and see what kind of error you get.)
  4. These functions are defined in a file called syscall.s. Download this file and assemble it into an object file.
  5. Now you're ready to build an executable. Link the two object files (hw3.o and syscall.o) as follows: java asm.Linker hw3.o syscall.o. This should produce an executable (a.out).
Now run the resulting a.out in the simulator. Hopefully, you'll get the same result as above.
__start() {
  int N = 9;
  int result = 1;
  while (N != 0) {
    result = result * N;
    N = N - 1;
  }
  printString("The factorial is: ");
  printInt(result);
  exit();
}
Answer the following questions. How many cycles does it take? How many load instructions are executed by the program? How many arithmetic instructions are executed?






Finally, modify the above C-- program in the same manner as you modified the assembly program (above). It should call the function readInt to get an integer from the user. Below is an example C-- program that uses readInt:
__start() {
  printString("Please enter a number: ");
  int x = readInt();
  if (x < 0) {
    printString("Your number is negative.\n");
  }
  else {
    printString("Your number is non-negative.\n");
  }
  exit();
}
Contrast the tradeoffs between programming in C-- and assembly code. How long did it take you to make the respective modifications?

Deliverables

Please stay tuned.
dugan@cs.washington.edu