Spring 2001 CSCI 255 Lab 11

This lab is scheduled for the week of 9 April - 11 April.

Goals and Methods

This week we'll look at some nifty Unix programming tools.

Getting started

Begin by executing the following commands to create a directory csci/255/lab11 and copy seven files into it.

The copied files should will look familar to you. Most of them were used in Lab 10. The difference is that the asm files from last week have been replaced by c files. Also, the lab10b files have been omitted.

The make program

Go ahead and type the make command. This week you'll get an error message.

The problem is that make is trying to use nasm to generate a .o from a .asm file when it should be using gcc to generate a .o file from a .c file. Your first task is to fix this problem. You can do this simply by modifying the Makefile containing in your directory.

We can't teach you all about make in a lab. There are entire books, such as Oram and Talbott's Managing Projects with make, and several on-line tutorials, such as Yoshino's Make - a Tutorial, on the subject. However, we can introduce a few features of make. Before you dismiss make as yet another obscure Unix program, we'll point out that even Visual Studio has some support for make and that, if is wasn't for Microsoft's make, your 201 instructor would not have been able to automatically compile all your 201 programs.

The basic action of make is to build a dependency graph of your program, in which target files are associated with source files, and to then compile and link only those programs necessary to bring your entire project up to date.

Start up pico and read in the Makefile in your directory. Notice the two-line entry:



lab11:		main11.o readdec.o prnthex.o
	gcc -o lab11 main11.o readdec.o prnthex.o

The first line specifies a target lab11 and three source files main11.o, readdec.o, and prnthex.o. The second line gives a command for generating the target from its sources. One of make's less endearing features is the the second line must begin with a tab.

When you type the command make lab11, the make program will look for an entry with the target lab11. The three source files of that entry because new targets for make. It now looks for other entries with those target files as source, such as:


main11.o:	main11.c
	gcc $(CFLAGS) -c main11.c

This process continues until all source files necessary to generate lab11 are discovered. Some of these source files are leaf files that are constructed by the programmer, not the compiler. The C file main11.c is a leaf file.

If a leaf files is missing, make gives up and informs the programmer. This is what's wrong with our buggy Makefile. It tries to use a non-existent leaf file readdec.asm. The appropriate leaf for this case is readdec.c.

If all leaf files are located, make will attempt to build the program. If there are missing target files, make will use the appropriate entry commands to generate the target from its sources. If make discovers that a target is older than any of its sources, it will regenerate the target so that it is up-to-date.

Let's get back to our computers. Our immediate problem is that our Makefile has several bad source files. Look for entries that attempt to generate .o files from .asm files, such as:


prnthex.o:	prnthex.asm
	nasm -f elf -o prnthex.o prnthex.asm

Replace these with an appropriate entry for a C source file.


prnthex.o:	prnthex.c
	gcc $(CFLAGS) -c prnthex.c

After you've make all these changes, you should be able to type make and link the lab11 program.

A bit more about make

Now, let's see how make only compiles the files that really must be changed. Use the pico editor to modify the file prnthex.c so that the letters of the hexadecimal digits are printed in lower case rather than upper case. You only need to change one letter to do this.

Then run make again. Notice that only one new object file and only one new executable file are generated.

A bit more about C and assembly

Remember those assembler language files from Lab 10? They were generated by a two-step process. First the gcc compiler was invoked with the -S option. Go ahead and do that on the file readdec.c. This will generate readdec.s, an assembly file in "AT&T" format. AT&T format is a bit more like the old PDP assemblers used in the early days of Unix. To convert the program into Intel format, you need to use a public domain program called a2i.

Remember how last week you improved readdec.asm by removing a single instruction. This time improve readdec.s by removing the same instruction, except now the file is in AT&T format.

A bit more about an executable

Ever wonder what is stored in any executable program? Type the following command to examine a listing of the headers within the executable lab11.

As you look at this output, answer a couple of questions about the executable on the Lab 11 check-off sheet.

A bit about gdb

Start up the GNU debugger, gdb, on executable lab11 by typing the following command.

Once you are runnning gdb, type the following commands in order to figure out how to set a breakpoint.

Now set a break point for the procedure prnthex. When you succeed, you'll get a message similar to:


Breakpoint 1 at 0x8048633: file prnthex.c, line 2.

Now type the command run to begin execution of your program. You should be prompted, by your program for a positive decimal number. Enter one. Soon the breakpoint will be encountered.


Breakpoint 1, prnthex (X=0) at prnthex.c:2
2         X = X & 0xF ;                   

Type the command bt to see a backtrace of the stack. On the check-off sheet, write the value of the envp argument of main.

Type print envp[1] to print the value of the second element of envp. That doesn't work because you're at the wrong stack level. Type up to go up to the level of main and then obtain the value of envp[1] and print it in the lab check-off sheet. Then use down to return to prnthex.

Use the commands print $sp, print $ebp, and print $pc to obtain the values of the stack pointer, base pointer, and program counter. Write them on the check-off sheet.

Type list to look at the next few lines of code in C and then type disassemble to list the new few IA-32 instructions. What is the first instruction stored after prnthex+10?

Use the following three commands to print the old base pointer, return address, and argument as they are stored, in order, on the stack. Write these values on the check-off sheet.


x $ebp
x $ebp+4
x $ebp+8

Just for fun manually set the value of the first argument using the following command.


set *((char *)($ebp+8))=10

Use the command clear to remove the breakpoint and type continue to continue execution of your program. Finally, type quit to exit from gdb.

Going home

Turn in your lab check-off sheet but do not delete your files.