Readings (from BOH3)
Section 2.1 (you can skip 2.1.7 for now, on
bitwise operations, and 2.1.9 on shift operations)
Section 2.2 (don't sweat the B2Uw notation for now, though all it's doing is formally defining the conversion from strings of bits to integers)
Section 2.3 on integer arithmetic (we'll save floating point, in 2.4, for later)
Due: Friday, February 1
Write a C program with the following functions:
1. printbox(char* str, int margin): prints the string str in a box. The margin parameter indicates the number of spaces between the string and the sides of the box. In the example below, str="hello, world!" and margin=4.
* hello, world! *
You will need a loop to print spaces and '*'. One way to print a single character c is with putchar(c); another way is with printf("%c", c).
2. unicoder(char * str): prints the string with all non-ASCII bytes replaced by a two-character hex code. This will let you know how the unicode characters are really represented.
A character c is ASCII if (32 <= c && c <= 127). This works if c is signed or unsigned.
To print c as a two-character hex code, use this. (The "c" might very well be "*p" if you use a pointer)
printf("%02x", (unsigned char) c)
The cast to unsigned is important! See also BOH3's show_bytes() on page 45. If you want, you can enclose each hex code in <>, eg with printf("<%02x>", (unsigned char) c), so the output might look like <3a><e9><bf>.
Run the program on the following strings:
char * str1="⍺";
char * str2="alpha is ⍺, beta is β and mu is µ";
I've placed the above two lines of code in h1strings.c, in my directory. One option is to copy this file and use that to start your program, or copy the contents into your program.
You can also copy the strings above and paste them into your program. To do that using guacamole, copy them and then, in guacamole, press SHIFT-CTRL-ALT and paste them in the clipboard box that appears in the lefthand sidebar. Then press SHIFT-CTRL-ALT again to hide the sidebar. Now a right mouseclick should paste the clipboard contents.
Finally, you can just copy the h1strings.c file and link to it. Write your own file in which you declare extern char * str1; extern char * str2, and then compile your file and mine together with gcc yourfile.c h1strings.c.
You will need the following header files:
#include <stdlib.h> // maybe you don't actually need this one for this assignment, but it's good to have
Accounts have been set up for everyone on boole.cs.luc.edu (not accessible from the outside world). Your userid is your Loyola UVID, and your initial password is the letter 'p' followed by the last five digits of your student P-number ("pxxxxx").
Logging in is complicated. The normal way is via ssh, using your supplied username and password. But ITS blocks that over the LUC wi-fi, though I'm trying to work with them on that as this block appears completely unnecessary.
Method 1: Use our "guacamole" server, which involves logging in via a web page. Go to perlis.cs.luc.edu with your browser, and log in with your UVID and the pxxxxx password (I don't think there is any way to change the latter). Click the login button, and choose boole.cs.luc.edu as your desired destination (if there is a choice, which there may not be). You then should get a login prompt for boole, which should take your usual credentials and give you a terminal window.
Method 2: Set up Loyola Secure Access. You should already be authorized for this. See www.luc.edu/its/uiso/resources/lsa.shtml.
Method 3: Find a wired Ethernet jack and use that. There are several in Doyle.
Here is a very brief tutorial on getting around in bash (the linux shell):
ls: list your files, like windows "dir"
ls -l: long listing
mkdir: make a directory, like windows "mkdir"
cd: change to a new directory, like windows "cd"
gcc -o foo foo.c: compile program foo.c into executable foo.
make foo: does the same as above
nano foo.c: a simple editor.
cat foo.c: display the file foo.c on the terminal. The
name comes from "catenate", because you can string together multiple files
pwd: print the current working directory
file foo: identifies what kind of file foo is
memory.c: I've changed it so everything is long. That makes it easier to figure out what's going on.
C: see c.html
rows_and_columns.c: an illustration of the effect of caches. Row order and column order visit exactly the same array components, but in different orders.
branchpredict.c: an illustration of the effect of branch prediction. The two array passes -- before and after sorting -- do exactly the same work, just in different orders. Also, what's with that 'µ'? Is it a byte?
Friday 1/25: demos of char * p, strlen(), strcmp(), strcpy()
What does the program do? What happens if we get rid of the unsigned? Why "%02x"?
Advantages of little-endian byte order
Above is 65536+24 = 65560, in little-endian byte order. As hex, it is 0x00010018 (why?).
Little-endian amounts to thinking of the number in base 256 (that is, as four full-byte units), and writing them right to left. Why would you do that?
Possible reason one: on 8-bit systems, where you load one byte at a time, if you want to add two 32-bit quantities you can start as soon as the first byte is loaded. On big-endian systems you have to wait for the last byte to be loaded before you can start doing arithmetic. (But you could also create opcodes such as "load low-order byte of 32-bit word pointed to by register r1")
Possible reason two: if p is a pointer to the above, so p points to the low-numbered byte, that is, the lefthand one, then p points to:
There are times when this is a convenience, again, probably mostly for very simple CPUs. There are similar, but kind of technical, advantages for big-endian byte order. There is also one large programmer benefit for big-endian: numbers printed in memory dumps look the same way they do when written ordinarily. This makes that kind of debugging quite a bit easier. That said, today debugging from hex dumps is relatively rare. (I still do it when examining network packets, though.)