From CS61
Jump to: navigation, search

Assembler: Learning to Read

Learning Objectives

  • Convert C programs into assembly
  • Use gdb and objdump to examine the assembly underlying a C function/program (Note: objdump is a GNU tool, so you need to use gcc instead of clang to compile files if you want to use objdump.
  • Read simple assembly
  • Become comfortable with the typeless nature of assembly

Getting Started

Pull today's exercise code from the cs61-exercises repository. We strongly encourage you to use the appliance today -- if you use your laptop, you are likely to get assembly code that looks quite different from what we expect and the observations we ask you to make and questions we ask you may be difficult to answer.

Varieties of functions that do nothing

In the asm-intro video, we introduced the function func that took no parameters, did nothing, and returned nothing. That function is in the 1.c file in today's directory. Create a few variants of this function that take parameters and/or return a value and compare the assembly produced for the different variants (we recommend you name these variants 1a.c, 1b.c, etc (for consistency with some other examples we'll be doing). You can convert c files to assembly without modifying the Makefile just by typing make 1a.s. Alternatively you can add these to the all target in the Makefile and just type make.

Include at least one variant that returns 0. Notice the assembly produced. Can you think of another way the compiler might have chosen to implement the return value? Why do you suppose the compiler chose the instruction it did? Build a .o file and use objump to examine the code produced -- does that change your hypothesis.

The Sum Function

In the asm-operators video, we introduced the simple sum function, which you will find in the file 2.c. In addition, you will find three other files 2a.c, 2b.c, and 2c.c. Note that each of these differs slightly from 2.c in C, but produces identical assembly code. These examples highlight the difference between the C abstract machine, in which the programs are different, and the actual machine, where they are executed identically. Your task is to come up with as many other variants of the sum function that will produce the same assembly. Experiment with different parameter types and different ways of instructing the compiler to produce code that adds two numbers together. Spend at least five minutes trying to come up with some variants, but no more than 10 minutes.

Next, examine 3.c, 4.c, 5.c, and the s files they produce. Subtraction (3.c) and Multiplication (4.c) are pretty predictable, but the assembly for 5.c has a couple of interesting features. Use google or any other resource to figure out the answer to two questions:

  • What does cltd do?
  • Why does idivl take only one operand?

Operands of Different Sizes

Now create versions of the functions in 2.c-5.c with a variety of different types of different sizes, e.g., char, unsigned char, short, unsigned short). Pay particular attention to the following issues:

  • How are signed and unsigned values treated differently?
  • How are operands of different sizes treated differently?

Bit Operations

In the video on operators you saw that there are logical operators as well as arithmetic ones. Let's experiment with some other related operations.

Examine the program 6.c. What is it doing?

Now build and examine the file 6.s. There are two interesting things about it:

  • Note that although the second parameter is unsigned, the assembly code moves only a single byte in %cl. Why?
  • Note the shll instruction. What do you suppose it does?

Next take a look at 7.c -- can you predict what code it will generate? Build and examine 7.s to see if you were right. Why do you suppose I implemented mul4 and not just mul2? If you can't figure it out, write mul2 and see what happens.

Next take a look at 8.c. Build and examine 8.s. Is it what you expect? Predict any difference you might see if you change the parameter to an int instead of an unsigned. Then test it.

What happened? (Use Google or any other resource easily available to explain any instructions you don't understand.)

Write a function that just divides its parameter by 4. What do you expect to see in the assembly? Check your answer.

Moving things around in Memory

Write a simple C function, swap.c, that takes two pointers to integers and swaps their contents. Then produce the assembler output for that function. Try reading the assembly output and see if you can figure out what it's doing. Use scrap paper or a whiteboard to draw what's happening.

Examine what happens if you change the parameters and return values to be pointers to differently sized things. What happens?

Summing Up

  • You can read assembly for simple programs!
  • You have probably figured out how/where parameters are passed to functions
  • You know how assembly instructions express arithmetic and logical and shift operators
  • You have discovered just how smart the compiler is some times!

Please complete this short survey.