Instructions

page 1 of 15
ENCM 369 Winter 2015 Lab 1
for the Week of January 19
Steve Norman
Department of Electrical & Computer Engineering
University of Calgary
January 2015
Lab instructions and other documents for ENCM 369 can be found at
http://people.ucalgary.ca/~norman/encm369winter2015/
1
Administrative details
1.1
Each student must hand in his or her own assignment
Later in the course, you will be allowed to work in pairs on some assignments.
1.2
Due Dates
The Due Date for this assignment is 3:00pm Friday, January 23.
The Late Due Date is 3:00pm Monday, January 26.
The penalty for handing in an assignment after the Due Date but before the Late
Due Date is 3 marks. In other words, X/Y becomes (X–3)/Y if the assignment is
late. There will be no credit for assignments turned in after the Late Due Date;
they will be returned unmarked.
1.3
B
G
H
total
1.4
Marking scheme
6
6
4
16
marks
marks
marks
marks
How to package and hand in your assignments
Please make sure all your work is easy to read and conveniently organized; this will
be a big help to the teaching assistants who have the difficult job of marking your
assignments.
Make a cover page with this information on it, in large, easy-to-read handwriting
or printing, . . .
• your name (but not your ID number)
• your lab section number (B01, B02, B03 or B04)
• the name of this course—ENCM 369
• which lab assignment it is—Lab 1 this week, Lab 2 next week, and so on
ENCM 369 Winter 2015 Lab 1
page 2 of 15
Staple your assignment together. Assignments held together by paper clips or by
folding corners of pages together will almost certainly fall apart in the collection
boxes, and teaching assistants are not responsible for re-collating loose pages they
might find.
Please check carefully that you are handing in all of the material you are supposed to be handing in. “I forgot” is not an acceptable excuse for handing in part
or all of an exercise after the Due Date.
Hand in your assignment in the box for your lab section in the west hallway on
the 2nd floor of the ICT Building. Before letting your assignment fall in to the box,
please double-check that you are handing it in to the correct box!
2
Editing and running C programs using a text
editor and the gcc command line
Note: This section was written for students in Winter 2014 who might never have
run gcc from the Linux command line when ENCM 369 started.
In Winter 2015, most ENCM 369 students will have used gcc on the Linux
command line many times in ENCM 339 in Fall 2014. Nevertheless, it might be a
good idea to review this material.
2.1
Why use the command line?
Many programmers prefer to develop software in IDEs (integrated development
environments), such as Eclipse, Microsoft Visual Studio, and Apple Xcode.
However, for the small C programs you will work in this course, we would prefer
you to edit them in a general-purpose text editor, then build executable files and
run them in terminal windows.
The main reason for this is that running gcc from a command line helps you
understand the “nuts and bolts” of putting a program together, in a way that
might be somewhat hidden from you if you were to use an IDE. This won’t be very
apparent in Lab 1, but will be more so in later labs, especially Lab 5.
2.2
Terminal windows and the shell
(These instructions are specific to Linux as it has been set up in Schulich School of
Engineering student labs. If you use another Linux distribution you will find your
environment similar but not exactly the same.)
To open a terminal window, use
Applications→System Tools→Terminal
which means, “Start with the Applications menu, select System Tools, then select
Terminal from the System Tools menu”. (Or just click on the terminal icon in the
menu bar at the top of the screen.)
A shell is a program that allows users to run other programs. When you open
a terminal window, there is a command-line shell called bash running within the
window.
2.3
Directories
Directory is another word for what Windows and Mac OS X users usually call a
folder. That’s helpful to know for many reasons, including remembering the names
of shell commands such as cd (change directory), pwd (print working directory),
mkdir (make directory), and so on.
Here are a few things to know about working with directories in the shell:
ENCM 369 Winter 2015 Lab 1
page 3 of 15
• When typing a command, there must be a space between the command name
and the first argument. For example, cd.. will not work, because there is no
space between the d and the first dot; what you need is cd ..
• / (slash, not \, which is a backslash) is the directory separator symbol. For
example, foo/bar/quux.c names a file called quux.c within the directory
bar, which is within the directory foo.
• It’s easiest not to have any spaces within names of files and directories, and
to use only letters, digits, -, _, and ., not any other punctuation characters.
• An instance of the shell has, at any given moment, a working directory. Access
to files in shell commands is normally relative to the working directory. The cd
command can be used to change the working directory; some examples of cd
can be found in Figure 1.
• Here are a few special symbols for directories within the file system:
.
..
~
working directory
directory one level up from working directory
user’s home directory
For example, suppose you have a directory called encm369 in your home directory, and within encm369 you have two directories called lab01 and lab02.
No matter what the current working directory is, you can make lab01 the
working directory with
cd ~/encm369/lab01
If you then realize that you really wanted to be in lab02, you can get there
quickly with
cd ../lab02
2.4
Copying, moving, renaming and removing files
Using your experience with graphical file-browsing tools (such as Windows Explorer
or “My Computer”, or the Mac Finder), you should find it easy to perform these
kinds of operations in the Linux environment. Start with the Places menu.
If you would like to learn how to do this using shell commands instead, the shell
commands are cp (copy), mv (move or rename, depending on arguments), and rm
(remove). There are many good tutorials on the Web that can help you with these
commands. Two good ones for beginners are:
http://linuxcommand.org/lc3_learning_the_shell.php
https://help.ubuntu.com/community/UsingTheTerminal
2.5
Text editors and gedit
A text editor is a general-purpose program for editing the sequence of characters
in text file. A good text editor can be used to edit source code for many different
programming languages, HTML source for Web pages, Linux system configuration
files, and any other kind of file that is really just a sequence of character codes.
Unless you already know how to use one of vi or Emacs—two very powerful
text editors available for most operating systems—I recommend that you use a text
editor called gedit to edit C code, because it is very easy to learn. (As a bonus, it
also formats text files very nicely for printing.)
To start gedit via the Applications menu, do
ENCM 369 Winter 2015 Lab 1
page 4 of 15
Figure 1: Examples of important shell commands for working with directories.
command
pwd
cd
cd ~
cd ..
cd foo
mkdir bar
ls
ls -a
ls -al
meaning, remarks
Print working directory. (Displays it in the terminal—does
not send it to a printer!)
Change working directory to home directory.
Another way to change working directory to home directory.
Change working directory one level up (in other words, to
the directory containing the current working directory).
Change working directory to foo—error if current working
directory does not contain a directory called foo.
Make a directory called bar within the current working
directory.
List files and directories within the current working directory.
List all files and directories within the current working directory, even those that whose names start with a . character.
Get long listing of all files and directories within the current working directory. Useful for finding out sizes of files,
and dates and times of last modification. (Last character
is letter l, not digit 1.)
Applications→Accessories→gedit Text Editor
Within gedit, there are a few preferences that I recommend changing, to help
with editing of C code. (You only need to do this once, not every time you edit a
file.)
• Bring up the Preferences window using Preferences from the Edit menu.
• On the View tab, check Highlight matching bracket.
• On the Editor tab, change the Tab width to 4; then check Insert spaces instead
of tabs and Enable automatic indentation.
2.6
Building executables with the gcc command
An executable file (often called simply an executable) is a runnable program, a file
containing machine instructions and other necessities. If an executable is generated
starting from some C code you have written, the executable will contain, among
other things, machine instructions corresponding to all of your C function definitions.
Generating an executable from C code on Linux generally involves one or more
uses of the gcc command. (If you use an IDE such as Eclipse, or a build tool such
as make, the IDE or build tool will run gcc for you, as many times as necessary.)
gcc offers a very large and somewhat intimidating set of options. Fortunately,
we only need two of those options in this lab assignment, and a only few more in
later assignments.
Suppose you have written a C program in a single file called mycode.c. You can
try to build an executable called a.out with this shell command:
gcc -Wall mycode.c
ENCM 369 Winter 2015 Lab 1
page 5 of 15
(Use of the -Wall option—which generates warning messages for a lot of kinds of
C code that can be compiled but are probably incorrect—is not mandatory but
is highly recommended.) If there are errors or warnings, they will appear in the
terminal window. If the command is successful, you won’t get any messages at all,
and a new version of a.out will be created.
To run the executable a.out, the command is
./a.out
Putting ./ at the start of the command tells the shell to look in the working
directory for an executable, rather than in other parts of the file system. You
should only try to run an executable if the most recent build was successful—if not,
you will either not be able to run anything, or you will run an out-of-date version
of the executable.
If you would like your executable to have some name other than a.out, that’s
easy to fix with the -o option. For example, if your one and only source file is
myprog.c, and you want your executable to be called myexec, the correct shell
command would be
gcc -Wall mycode.c -o myexec
If the build is successful, you can then run the program using the shell command
./myexec
What if you want to build an executable from two or more .c files you have
written, plus some number of related .h files? That isn’t hard to do, but isn’t
something you need to do for this assignment, so I’ll put off explaining it until later
this term.
3
Compiler error and warning messages
When the compiler finds a problem in your source code it generates one of two types
of messages: errors and warnings. If the word warning appears in the message, it
is, logically enough, a warning. Otherwise it is an error, even if the word error
does not appear.
An error means that something in your code violates the rules of C, meaning
that the compiler cannot translate the source code. In the case of an error it is
obvious that your program must be fixed.
A warning, on the other hand, is generated when the compiler finds something
that is legal in C but is bad style or has a meaning that is probably not what you
intended. If there are warnings but no errors, the compiler will translate your source
code.
If you get more than two or three errors or warnings, it is best not to try to
fix all of them at once, because problems nearer the beginning of your C code
may confuse the compiler so much that completely valid C code farther along will
generate warnings or errors for no good reason.
4
Creating input/output records with termrec
termrec is a utility which allows you to make a record of your program input and
output. You might be familiar with it from some previous course. If you haven’t
used termrec and could use some help with it, see this Web page:
http://people.ucalgary.ca/~norman/encm369winter2015/termrec/
Here are a couple of reasonable alternatives to using termrec:
ENCM 369 Winter 2015 Lab 1
page 6 of 15
• It’s possible but sometimes tedious to copy-and-paste text from a terminal
window into a text editor or word processsing program.
• If you use Emacs and are willing to spend some time learning how to use the
shell command within Emacs, that will give you a very convenient way to
save a record of your work.
5
Exercise A: Practice editing C code and building
an executable
5.1
Read This First
There are no marks for this exercise, but I strongly recommend that you make a
serious effort to get it done before your first lab period. If you are unsuccessful,
please be ready to ask questions at the beginning of the lab period.
5.2
What to do
Review Sections 2.2 to 2.6 carefully.
Open a terminal window. Create a directory called encm369. Within your
encm369 directory, create a directory called lab01, and within that create a directory called exA.
Figure 2: C code for Exercise A.
#include <stdio.h>
int main(void)
{
int n = 0;
int power = 1;
printf("%12s%12s%12s\n", "n
", "2**n
", "2**n");
printf("%12s%12s%12s\n", "decimal", "decimal", "hex ");
while (n <= 16) {
printf("%12d%12d%12x\n", n, power, power);
power = power + power;
n++;
}
return 0;
}
Start up gedit (or some other text editor, if you know that text editor well).
Type in the first line from Figure 2, then use a Save as . . . command to save the
file with name exA.c, in your encm369/lab01/exA directory. Use the ls command
to confirm that a file called exA.c exists within that directory.
Return to the text editor, and finish typing in the rest of the code from Figure 2.
When you have finished, save the file and return to your terminal window.
In the terminal window, build an executable with the command
gcc -Wall a.out
ENCM 369 Winter 2015 Lab 1
page 7 of 15
If there are errors or warnings, go back to the text editor, try to fix the errors,
then try again to build an executable. If there are no errors or warnings, run the
command
./a.out
You should see a table of powers of 2n for values of n from 0 to 16, displayed in
both base ten and base sixteen.
Keep working on this exercise until you are sure you know what you are doing—if
you do not, you will have serious problems with all of the remaining exercises!
5.3
What to Hand In
Nothing.
6
How to download files for ENCM 369 labs
Most lab exercises in this course will require you to download one or more files
containing C code, assembly language code, or data.
Links for downloading these files can be found on the same Web page where you
find lab instructions. You have the option of clicking through links to get files one
at a time or downloading all the files you need for one lab in a single .zip archive.
When you are told to make a copy of, for example,
encm369w15lab01/exB/globals.c,
you should look for it starting on the ENCM 369 Lab Information web page.
7
7.1
Exercise B: Global variables, review of pointer
arithmetic
Read This First
Most variables you saw or created in programs in ENCM 339 were local variables. A
local variable can be directly accessed only within the function definition in which
it appears. (A local variable of one function can be indirectly accessed by another
function, if that other function has a pointer to the variable.)
C variables declared outside of all function definitions in a C source file are called
global variables or external variables. Unlike local variables, global variables can be
directly accessed from many different function definitions.
There are two kinds of global variables: those declared to be static and those
not declared to be static. Global variables declared to be static can be directly
accessed by all functions in the source file where the variable is declared. (This
use of the keyword static is confusing, because it has nothing to do with static
memory allocation.) Global variables not declared to be static can be directly
accessed by all functions in a program.
(If you are working on a program where a global variable is in fact accessed
from more than one source file, you need to know the rules regarding the extern
keyword. See a good C text for details, and read carefully.)
Global variables, regardless of whether they are declared as static, are always
statically allocated. So, according to rules you should have learned in ENCM 339,
global variables are found in the static storage region, are allocated and initialized
before main starts, and remain allocated as long as the program runs.
Unlike automatic variables (which are the “normal” kind of local variables of
functions) global variables that don’t have initializers are initialized to zero. For
example, consider this variable declaration:
ENCM 369 Winter 2015 Lab 1
page 8 of 15
int arr[5];
If arr were local to some function, you could not count on the elements of arr to
have any particular values. But if arr were a global variable, its elements would all
be initialized to zero.
7.2
7.2.1
What to do
Part 1
Copy the file encm369w15lab01/exB/globals.c
Study the file carefully and make sure you understand the diagram of program
state at point one given in Figure 3.
Make a similar diagram to show the state of the program when it reaches point
three. (Note: In ENCM 369, whenever you are asked to hand in diagrams, you may
draw them neatly by hand or by computer, whichever you find more convenient.)
Figure 4 should give you a hint about how to draw part of the diagram.
Figure 3: The state of the Exercise B program at the moment when point one is reached.
At that moment, functions update and reverse are not active, so their arguments and
local variables do not exist. The notation ?? is used to indicate uninitialized local variables.
Important note for ENCM 369: As the course progresses, we will see that some of
the local variables and arguments of a program are in a region of main memory called the
stack, and other local variables and arguments are in registers; we’ll see later in the course
that for MIPS the arrays alpha and beta would be allocated on the stack, but the integers
and pointers belonging to copy would be in general-purpose registers, not in memory at
all!
statically allocated
memory
epsilon[0] 5000
6000
7000
8000
epsilon[4] 0
0
delta[0] 222
333
444
delta[3] 555
bar 2100
local variables
and arguments
4
i
4
n
copy
from
to
5000 beta[0]
6000
7000
8000 beta[3]
??
??
??
??
??
alpha[0]
alpha[4]
main
ENCM 369 Winter 2015 Lab 1
page 9 of 15
Figure 4: Example of a pointer pointing “just beyond” the last element of an array.
Here arr[3] does not exist, but the address of arr[3] does exist. This concept is useful
for setting up a condition to quit a loop, when the loop uses pointer arithmetic to step
through an array.
// fragment of a C function
int arr[] = { 10, 11, 12 };
int *p;
p = arr + 3;
10
11
12
arr[0]
arr[2]
p
Figure 5: Table for Exercise B, Part 2.
instant in time
point two, first time
point two, second time
point two, third time
point two, last time
7.2.2
src
0x100020
beyond
d
Part 2
Instead of using arrows to show what addresses are contained by pointers, let’s track
pointers as actual numbers.
We’ll assume that the size of an int is 4 bytes. We’ll use hexadecimal numbers,
writing them in C language notation. For example, 0x7ffe18 represents a number
we would have written as 7FFE1816 in ENEL 353.
Suppose that the address of ccc[0] in main is 0x7ffe18. Then the addresses
of elements 1, 2, 3 in the array must be 0x7ffe1c, 0x7ffe20, and 0x7ffe24—each
address is 4 greater than the previous one. (Here is a fact you will use often in this
course: In base sixteen, adding 0xc and 0x4 generates a sum digit of zero and a
carry out of one.)
Now suppose that &epsilon[0] is 0x100020 and &alpha[0] is 0x7ffe28. Use
that information to fill in all of the addresses in all of the cells in a copy of the table
in Figure 5.
7.3
What to Hand In
Hand in a diagram for Part 1 and a completed table for Part 2.
8
Using your own computer for Exercises C–H
We (your instructors and TAs) expect that most students will do Exercises C to H
on Linux workstations in ICT 320. However, all of the exercises can be done on your
own computer, if you have a reasonably up-to-date C development system installed.
All students should do at least two or three of the exercises in ICT 320, just to
get comfortable with the process of editing C code and building executables using
a text editor and a command line.
ENCM 369 Winter 2015 Lab 1
9
9.1
page 10 of 15
Exercise C: goto statements
Read This First
goto statements are available in C and C++, and their equivalents are available in
most programming languages.
You can have a long career writing high-quality C and C++ code for a huge
variety of applications and never once use a goto statement. Just about everything
you can do with goto can be done more clearly some other way. Use of goto tends
to make code unreasonably hard to understand and debug.
Nevertheless, it’s useful to know what goto does, for the following reasons:
(1) You might find goto in code that somebody else wrote.
(2) C code generated by a program (as opposed to code written by a
human being) may have goto statements in it.
(3) Writing goto statements is similar to writing branch instructions in
assembly language.
It’s reason (3) that makes the goto statement relevant to ENCM 369.
Consider the following simple program:
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i < 4; i++)
printf("i is %d. ", i);
printf("\n");
return 0;
}
Obviously, the output is
i is 0.
i is 1.
i is 2.
i is 3.
Here is an equivalent program written using goto statements:
#include <stdio.h>
int main(void)
{
int i;
i = 0;
loop_beginning:
if (!(i < 4)) goto past_loop_end;
printf("i is %d. ", i);
i++;
goto loop_beginning;
past_loop_end:
printf("\n");
return 0;
}
The output is exactly the same as that of the earlier program with the for loop.
The identifiers loop_beginning and past_loop_end are examples of what are called
labels. A label is used to name a particular statement; a colon must appear between
a label and the statement it names. A goto statement has the following syntax:
goto label ;
A goto statement causes the flow of statement execution to jump to whatever
statement is named by the label. This should be reasonably clear from the example.
ENCM 369 Winter 2015 Lab 1
9.2
page 11 of 15
What to Do
Determine the output of the following program by tracing its execution line by line
with a pencil and paper.
#include <stdio.h>
int main(void)
{
int outer, inner;
outer = 3;
outer_loop:
if (outer == 0) goto quit_outer_loop;
inner = 0;
inner_loop:
if (inner > outer) goto quit_inner_loop;
printf(" %d", 100 * outer + inner);
inner++;
goto inner_loop;
quit_inner_loop:
printf(" **\n");
outer--;
goto outer_loop;
quit_outer_loop:
printf("*****\n");
return 0;
}
Check your work by typing in the program, compiling it, and running it. (If it
doesn’t compile, goes into an infinite loop when it runs, or crashes, you have made
a typing error.)
9.3
What to Hand In
Nothing.
10
Goto-C: Read this before starting Exercises D–
H
From now on in this course, the term “Goto-C” refers to a programming language
that is C with the following modifications:
• The only kind of if statement allowed in Goto-C is the following:
if (expression) goto label ;
• Goto-C does not have the following keywords and operators:
else while for do switch && ||
• Goto-C does not have ?:, the conditional operator.
As you will soon see, Goto-C is an annoying language, significantly harder to read
and write than normal C. However, working with Goto-C will help you learn how
to code algorithms in assembly language.
Consider the following simple fragment of normal C:
ENCM 369 Winter 2015 Lab 1
page 12 of 15
if (x >= 0)
y = x;
else
y = -x;
The above is illegal in Goto-C for two reasons: the if statement is not in an
acceptable form, and the banned keyword else is used. One way to translate the
fragment to Goto-C is as follows:
if (x < 0) goto else_code;
y = x;
goto end_if;
else_code:
y = -x;
end_if:
Technical Note: The C standard does not permit code like the following:
void f(int i)
{
if (condition) goto L;
code
L:
}
The reason is that the label L is followed by a closing brace, which is not a statement.
To write standard-compliant code, use the empty statement—a semicolon all by
itself . . .
void f(int i)
{
if (condition) goto L;
code
L:
;
}
11
11.1
Exercise D: Translating if / else-if / else code
to Goto-C
What to Do
Copy the file encm369w15lab01/exD/temperature.c
Read the file temperature.c. Make an executable and run it. Then recode the
function report in Goto-C. Make sure that the output of your modified program
exactly matches the output of the original program.
11.2
What to Hand In
Nothing.
12
12.1
Exercise E: Simple loops in Goto-C
Read This First
Simple C while and for loops are easy to code in Goto-C. You need a statement
of the form
ENCM 369 Winter 2015 Lab 1
page 13 of 15
if (condition) goto label ;
at the top of the loop to skip past the end of the loop when appropriate and you
need a statement of the form
goto label ;
to jump backwards after the loop body has been executed. For example, this code:
while (i >= 0) {
printf("%d\n", i);
i--;
}
can be written as:
loop_top:
if (i < 0) goto past_end;
printf("%d\n", i);
i--;
goto loop_top;
past_end:
Remember that the condition to quit looping is the opposite of the condition to
continue looping.
12.2
What to Do
Copy the file encm369w15lab01/exE/simple_loops.c
Read the file and follow the instructions in the comment at the top of the file.
12.3
What to Hand In
Nothing.
13
13.1
Exercise F: && and || in Goto-C
Read This First
You should recall from ENCM 339 that short-circuit evaluation is used when the
&& and || operators are encountered in C (and C++) code. For example, the righthand operand of && is not evaluated if the left-hand operand is false. It’s quite easy
to translate expressions with && into Goto-C. For example,
if (y > 0 && x / y >= 10) {
foo(x);
bar(y);
}
can be coded as
if (y <= 0) goto end_if;
if (x / y < 10) goto end_if;
foo(x);
bar(y);
end_if:
Expressions with || can be coded in goto-C using a simple adjustment of the technique used for expressions with &&.
ENCM 369 Winter 2015 Lab 1
13.2
page 14 of 15
What to Do
Copy the file encm369w15lab01/exF/logical_or.c
Read the file and follow the instructions in the comment at the top of the file.
13.3
What to Hand In
Nothing.
14
14.1
Exercise G: A more complicated program in
Goto-C
What to Do
Copy the file encm369w15lab01/exG/exG.c
Read the file carefully. Make an executable using the following command:
gcc -Wall exG.c
Run the executable eight times, using the following text as input:
input
1.0 x
1.0 0
1.0 5
1.0 6
1.08 10
1.09 10
-0.4 3
-0.4 4
description
first run, test with invalid input
second run, also invalid input
third run
fourth run
fifth run
sixth run
seventh run
eighth run
Translate the definitions of main and polyval to Goto-C. Be careful to translate
every use of a C feature that is not allowed in Goto-C.
Test your modified program with the same input given above for the original
program. Make sure it always generates exactly the same output as the original
program.
14.2
What to Hand In
Printouts of the final version of your source file and a termrec recording of your
program runs with the eight specified inputs. (If you do this exercise using your own
computer, then, instead of using termrec, use whatever method is most convenient
for recording and printing the specified eight program runs.)
15
15.1
Exercise H: Nested loops in Goto-C
What to Do
Copy the file encm369w15lab01/exH/exH.c
Read the file, then make an executable and run it to check what the program does.
Translate the definitions of print_array and sort_array to Goto-C. Be careful
to translate every use of a C feature that is not allowed in Goto-C.
Make sure your modified program generates exactly the same output as the
original program.
ENCM 369 Winter 2015 Lab 1
15.2
What to Hand In
A printout of the final version of your source file.
page 15 of 15