Create a week04
subdirectory in your weeklylab
subdirectory and copy over some files:
cd
cd cs31/weeklylab
pwd
mkdir week04
ls
cd week04
pwd
cp ~chaganti/public/cs31/week04/* .
ls
Makefile conditions.c simpleops.c
1. Week 4 lab goals:
-
Disassemble binary executables with objdump, and gdb.
-
Recap ALU condition codes.
-
Explore real PC hardware.
2. Using gcc to generate IA32 assembly
Let’s try out gcc to build IA32 assembly files and .o
files and look at the results. Open up simpleops.c
.
We are going to look at how to use gcc to create an assembly version of this file, and how to create a object .o
file, and how to examine its contents. We are also going to look at how to used gdb to see the assembly code and to step through the execution of individual instructions.
If you open up the Makefile you can see the rules for building .s
, .o
and executable files from simpleops.c
. We will be compiling the 32-bit version of
instructions, so we will use the -m32
flag.
gcc -m32 -S simpleops.c # just runs the assembler to create a .s text file
gcc -m32 -c simpleops.s # compiles to a relocatable object binary file (.o)
gcc -m32 -o simpleops simpleops.o # creates a 32-bit executable file
To see the machine code and assembly code mappings in the .o
file:
objdump -d simpleops.o
You can compare this to the assembly file:
cat simpleops.s
3. gdb disassemble and instruction stepping
Next, let’s try disassembling code using gdb. With gdb we can execute individual IA32 instructions, examine register values, and disassemble functions. Do a make clean
then a make
to rebuild an IA32 version of the simpleops
executable file.
gdb ./simpleops
(gdb) break main
(gdb) run
In gdb you can disassemble code using the disass
command:
(gdb) disass main
You can set a break point at a specific instruction:
(gdb) break *0x5655550f # set breakpoint at specified address (gdb) cont (gdb) disass
And you can step or next at the instruction level using ni
or si
(si
steps into function calls, ni
skips over them):
(gdb) ni # execute the next instruction then gdb gets control again (gdb) ni (gdb) ni (gdb) ni (gdb) ni (gdb) disass
You can print out the values of individual registers like this:
(gdb) print $eax
You can also view all register values:
(gdb) info registers
You can also use the display command to automatically display values each time a breakpoint is reached:
(gdb) display $eax (gdb) display $edx
4. ddd, a graphical debugging interface
Next, we’re going to try running this in ddd instead of gdb, because ddd
has a nicer interface for viewing assembly, registers, and stepping through
program execution:
ddd ./simpleops
The gdb prompt is in the bottom window. There are also menu options and buttons for gdb commands, but we find using the gdb prompt at the bottom easier to use.
You can view the assembly code by selecting the View->Machine Code Window menu option. You will want to resize this part to make it larger.
You can view the register values as the program runs (choose Status->Registers to open the register window).
See Tia’s GDB Guide for more information about using gdb and ddd (see the using gdb to debug assembly code and examine memory and register values section).
Also see figure 3.30 on p.255 of the textbook.
5. Condition codes
Recall the CPU condition codes we talked about in class:
ZF: If the computed result is zero. SF: If the computed result's most significant bit is set (i.e., it's negative if interpreted as signed). CF: If the computed result caused an overflow, when interpreted as an unsigned operation. OF: If the computed result caused an overflow, when interpreted as a signed operation.
Assume %eax
holds the value 5
, and %ecx
holds 7
. Suppose we executed the following instructions:
-
subl $5, %eax
-
cmpl %ecx, %eax
For each of these instructions, which flags should be set?
5.1. Experimental verification
Now that think we know which flags would be set, let’s see if we’re correct. Open conditions.c in your text editor. We’ll use this simple C file to generate the above instructions (or, at least some very similar ones).
Run make, and let’s open ddd:
ddd ./conditions
Let’s open the register status information window (described in the ddd section above) and put a breakpoint at main:
break main
From here, we can step through individual instructions (via the ni
command). Let’s stop when we get to the second sub instruction (sub
$0x5
,%eax
). We can see that at this point, %eax
holds the value 5, as expected.
Now, execute the instruction with ni. Are the condition codes (in the eflags
register) what you expected them to be?
Now do the same with the cmp
instruction that comes a few instructions after the sub
we just examined.
The condition codes for your ALU should work the same way!
6. Computer Teardown
Log out, we’re taking a field trip! You’ve been assigned to a groups, and each group is assigned a computer that you can take apart.
The goal is to find as many parts of a computer as you can. We have tools available to remove parts from your computer, and here are a few links that may be helpful:
Try to identify some of the following:
-
the processor
-
RAM memory card(s)
-
the backplane
-
the chipset, PCI and Memory buses
-
expansion slots
-
the hard drive (what’s inside?)
-
the network interface card (NIC)
-
the graphics card
-
where do different ports go?
-
… then see what else you can find
Before leaving lab, please clean-up all spare parts, screws, etc. that you have removed by putting them in the boxes. You do not need to put the cases in the boxes, just all loose parts. CPU thermal glue is toxic, so just to be extra safe I’d recommend washing your hands after lab today. |