To get full credit for this lab, you must complete the 61c Mid-Semester Survey. In addition to being worth 1 point on this lab, the information you give us will really help us improve the course and give you a better learning experience for the rest of the semester. Your responses are strictly anonymous, although you will have to enter your 61c login so that we can make sure everyone does it. After you hit the submit button your answers to the other questions are separated from your login (rather thoroughly, in fact). Your TA can check that you completed it by using this utility, again protecting your answers from being associated in any way with your login. Thank you for taking the time to help us run this course better.
Assemblers output object files. Object files are binary files that
contain the machine code and data that corresponds to the assembly
code that you (or a compiler) wrote. Several object files can be
linked together to form executable files. Object files and executable
files can come in several different formats. The most common one is
the Common Object File Format (COFF). The purpose of this lab is to
familiarize you with the COFF file formats and to practice linking
several .o files together to form an a.out file.
On the lab computers, MIPSgcc is aliased to always use the -S option which generates assembly code. For this lab, you'll need to unalias it in order to generate object code. Before you start the lab, type:
% alias MIPSgcc mips-dec-ultrix4.3-gcc
Until now, we have been feeding a single .c file to gcc to get an executable file. For example, we would say:
gcc -o lisp lisp.c
to get an executable for project 1. Today we are going to walk through the compilation process to learn some interesting facts about object files and the link editor. Start by downloading the files stack.c, stack.h, and teststack.c. Look at the code and learn what it does.
From class, we know that the compiler executes the following steps to make your executable:
From lab 04 We already know how to do step 1. (i.e., invoke MIPSgcc with the -S option.) Right now we are going to jump all the way to step 2. To do this, we use the -c option instead of the -S option like this:
MIPSgcc -c -fno-delayed-branch inputfile
Run this command on the files stack.c and teststack.c. This creates the object files stack.o and teststack.o. As we know from lecture, these object files each have a .text section where the code lives, a .data section where some of the data lives, a symbol table that indicates where the symbols are defined, etc. If you were to open these files in a normal text editor, however, you would not see these sections. This is because the file is already binary. To read these files, we use a utility called an object dumper. The one we will be using is MIPSobjdump. Invoke it on the two object files like this:
MIPSobjdump -x -d stack.o > stack.o.dump
MIPSobjdump -x -d teststack.o > teststack.o.dump
The -x option tells MIPSobjdump to print information about all of the sections and the -d option tells it to disassemble the instructions in the .text section. Open the .dump files in your favorite text editor and look them over. There will be many fields that you do not understand but you should recognize certain things. In particular, the part that begins with the label "Sections:" tells you the section name, size size of the section, virtual memory address of the section (VMA), and some interesting flags (CONTENTS, ALLOC, etc.)
Question 1: When the object files are created, the absolute addresses of functions and data are unknown. Instead, relative addresses are specified in the left most column. What are the relative addresses of the functions isEmpty, Push, and Pop in stack.o?
Question 2: Look at teststack.o.dump. The main function calls several functions that are in the stack.o object file. However, at this stage of creating the executable, the addresses of those functions are unknown. What does the assembler put in place of the actual addresses in the jal instructions that call these funcitons?
Now we are going to use the linker to make an executable. To do this, we simply invoke MIPSgcc with the names of the object files. It knows based on the .o file extension that these are object files and do not require compilation or assembly. Here's how you do it:
MIPSgcc teststack.o stack.o
The output file is called a.out. It too is an object file. However, it does not have any unresolved references so it is executable. Like the other object file, opening it in a text editor is not very revealing. Instead, dump it using MIPSobjdump like we did before and open the resulting file. Note that there are MANY symbols in this file that we did not define. These are all linked in by default. You may ignore these symbols.
Question 3: What are the actual addresses of the funcitons isEmpty, Push, and Pop in a.out?
Question 4: What is the address of the structure ourStack in the final executable? What section is ourStack in?