Generating Assembly Code
Due Monday, April 30

Having generated intermediate code, you are now faced with actually generating assembly. Unless it is impossible for you, you should be generating assembly code for an x86 machine running either

If you do not have easy access to such a machine, please contact Amir.

On the course web page, there are several assembly references. The first one to look at is the Linux Assembly HOWTO, although the only sections that are relevant are those for gcc and gas (the Gnu assembler). Then, look at the 386 Assembly Reference Manual to see the syntax of the assembly instructions that the Gnu assembler recognizes.

Here's the basic idea:

The very first thing you should do is write a simple C program and look at the assembly code that gcc generates for it. You do this by

gcc -S simple.c

where simple.c is your simple program. gcc will generate an assembly file called simple.s . Your compiler should use the same naming convention (for function names) and calling convention. Note that in some versions of gcc/gas, function and procedure names have a "_" prepended to the front of them (hence, those names in assembly look like "_main", "_foo", etc). In other versions of gcc/gas, the names in assembly look just like the names in C. Just take a look at the simple.s file that you generate to see what your version of gcc does.


To simplify the assignment, your compiler should not accept declarations or operations on records. All assignments should be between integers booleans and strings. Only integers, booleans, or strings are acceptable as parameters.
Any violation of these restrictions should be flagged as an error with the error message "Not currently implemented".

Sizes of Values

Parameter Passing

Parameter passing is completely by value. That is, the value of every argument is copied into the activation record of the called procedure or function. For a string parameter, what is passed is the address of (pointer to) the string.

Returning Values
Register Allocation

At this point, you are not expected to perform any kind of sophisticated register allocation. Just be aware of which registers have special functions (indexing, etc.). Also, once a variable's value is moved into a register, try to use the register for subsequent accesses to that variable (until it is overwritten). However, you don't have to work hard to minimize loads and stores.

Compile-Time Information

Your compiler, during code generation, should keep track of at least the following information:

Code Generation
Code generation is divided up into roughly three parts:
  1. The layout/declarative section.

    You'll have one of these at the top of your program, which will have the space for all the global variables. It will also have a global string table, containing all the string constants used in the program, so that you can refer to them. After this, you will have the declaration for each function defined in your program. Functions will consist of the following:

  2. The actual code generated.

    You will need to write a procedure in your compiler for each kind of intermediate code construct (label, goto, binary op, etc.), which generates an equivalent assembly language statement. Note that these functions will of course have to use the space/type info, in order to calculate offsets into the activation record, etc. For a label statement, for example, you would have to generate a label. For an if statement, you will have to generate a compare statement and then the appropriate branch statement. Notice that param statements generally translate into copying parameters to the stack before the function call (see "parameter passing", above). Be sure to pass the parameters on the stack in such a way that the first formal parameter ends up is nearest to the base pointer (i.e. frame pointer). To accomplish this, arguments should be pushed onto the stack in reverse (i.e. right-to-left) order.

  3. The details

    This phase also has a number of details to get right, which will likely be the cause of many bugs. Expect to spend significant time debugging your code, and allow for that time. A short list of things to watch for is:

Good Luck!