Instructions
Transcription
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