next up previous
Next: Assembler Up: Irix Compilation and Assembly Previous: Irix Compilation and Assembly

C Compiler

The following C program prompts the user for an integer N, calls a factorial function to compute N! and prints the result. The C main() function is in the file main.c. The compiler writes the MAL symbolic code to the file main.s. The factorial function is stored in a separate file called factorial.s.

The C compiler command under Ultrix is cc. The -c option causes the compiler to stop after producing assembly code. The -S option specifies MAL symbolic code. The cc command is described in detail under man cc.


Examination of the compiler generated code in main.s reveals:

  1. Compiler generated labels have the form $$N, where N is a counter used to produce unique labels.
  2. The main function is called by the operating system according to the MIPS calling conventions.
  3. The .globl directive is used to export the name of the main function to the loader phase of the compiler.
  4. The .mask and .frame directives are used to describe the stack frame used by the main function.
  5. A variety of other directives are used by the compiler for debugging, tracing and optimization.
  6. The C I/O functions printf and scanf are called using the MIPS calling conventions.
  7. The factorial function is called using the MIPS calling conventions with N passed by value in $a0 ($4) and the result is returned in $v0 ($2).

The assembly code produced by the compiler employs many pseudo-op directives, such as .align, .loc, .ent, .file, .mask, .frame, .livereg, etc. More information on these directives can be found in the Chapter 8 of the MIPS Assembly Language Programmer's Guide. Directives such as .loc, .ent, and .file are used for debugging and tracing program execution. The .livereg directive tells the assembler which registers are in use before a function or system call to prevent incorrect code optimizations.

The .frame directive describes the stack frame used to call the main function and the .mask directive indicates which registers are saved on the stack by the main function. This information is used by the assembler to build a table of stack frames and their sizes in order to eliminate the need for an additional register to store the location of the top of the previous stack frame (frame pointer). The .frame directive does not allocate space on the stack or alter the stack contents or $sp in any way. The use of these directives to describe a stack frame which conforms to the procedure calling conventions is discussed in Chapter 7 of the MIPS Assembly Language Programmer's Guide.

In the MAL code in main.s, the .frame directive calls for a stack frame of 8 words (32 bytes) using $sp to hold the address of the top of the stack and $ra for the return address for the main function. The .mask directive tells the assembler which registers are saved on the stack. In this case, the .mask indicates that only $31 ($ra) is saved on the stack and that it is stored 3 words (12 bytes) above the bottom of the stack frame. This location is also 5 words (20 bytes) below the top of the stack frame.

The code in main.s shows that the local variables N and F are stored just below $ra on the stack in words 6 and 7, respectively, from the top of the stack, as shown below:

tabular2214

In addition to the return address and local variables, the C compiler allocates space on the stack for the parameters which are used in procedures called by main. In this case, 3 parameters are needed for printf, but the compiler always creates stack frames which are a multiple of 16 bytes. Thus, the actual frame size of 24 bytes is increased to 32 bytes, even though the top 4 words on the stack frame are never used. The bottom word of the stack frame may be used to store the previous frame pointer, but is not used in this case.

The file factorial.s contains a MAL version of the factorial function. The function is called by placing the value of N in $a0 ($4) and the result is returned in $v0 ($2). No stack frame is needed because only temporary registers are used and factorial calls no other procedures.

In the following example main.c and factorial.s are compiled together to produce an executable file named a.out.



next up previous
Next: Assembler Up: Irix Compilation and Assembly Previous: Irix Compilation and Assembly

CS 301 Class Account
Mon Sep 13 11:15:41 ADT 1999