CSE 378 Homework 4

Due: Wednesday 1/29/03
Work in pairs or individually

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.

An Aside on Mechanics: Your "Build Environment"

We'll be using Cebollita through a command line interface, using Cygwin, a (Unix-like) bash shell that runs on Windows. The lab machines have been set up to make this as easy as possible. To start a shell, Start/Program Files/Desktop Tools/cse378/ceb. When the shell comes up, a number of aliases will have been defined: cebcc to compile C-- programs, cebasm to assemble assember (.s) files into .o files, ceblink to link .o's into a.out's, and cebsim to run the simulator. (Type alias in the shell to see the full set of alias definitions, and to relate them to the Cebollita documentation.)  For example, you might give a command line like which is identical to but is easier to type and to remember.

If you want to run at home, you'll need at least to install Cebollita - see the Cebollita documentation. You might also want to install Cygwin (which I recommend in any case) - www.cygwin.com - and you'll need a relatively up-to-date version of the Java runtime - jre V1.4.0_03. To set up the aliases as in the lab, create a file named .profile in your Cygwin home directory (type cd in the Cygwin shell and you're in the home directory) with these contents. Even if this sounds complicated, you should be able to manage it, with a little effort. Install Cebollita first - it could be that it will simply work on your machine.

(Note: Cebollita is written in Java, and so you should be able to run it on a non-lab machine, even if that machine is running Linux or, say, Mac OS X.)

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

In the lab, you'll need to build an executable out of the provided program. This means:
  1. Start a BASH shell - on the lab machines, Start/Program Files/Desktop Tools/cse378/ceb. 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, use the cd command to navigate to the directory where you put fact.s. Then, at the prompt type: cebasm fact.s
  3. If this step was successful, you should find a file called fact.o has been produced in that directory. (You can type ls to find out.)
  4. Link the program. Now type ceblink fact.o. This should create a file called a.out.
These are the basic steps you'll always need to assemble and then link a program - that is, to go from a .s file containing a Cebollita assembler program to a Cebollita executable file. 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 cebdumpm fact.o should dump interesting information about the object file. Typing cebdumpe 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 (cebsim 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; transform it into an executable and then use the simulator to execute it:
  1. Compile: cebcc hw4.c. This will create a file called hw4.s.
  2. Now assemble hw4.s (as above).
  3. In the earlier exercise, at this point you would link the hw4.o file to create an executable. But, linking is a little trickier now, because hw4.c 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 ceblink hw4.o, we'll get an error. Try it and see what kind of error you get.)
  4. These functions are, of course, just software. They're defined in a file called syscall.s. Download this file and assemble it into an object file - syscall.o.
  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.