2. Stack Diagrams, Linux Basics, Compilation

Day 2 (1/24/22) - Stack Diagrams, Linux Basics, Compilation #

Announcements #

  • We will meet remotely on Friday, 1/27/22 as well.
    • For various reasons (isolation, flooding, etc), some students are not yet able to attend in-person class.
    • Hybrid setups are tough to do well.
  • If you are not on Discord yet, please join as soon as you can.
  • Announcements for this course will be posted to the #announcements channel on Discord (and only there).
    • It doesn’t spam your email, and messages can be edited afterwards.
    • Also, it allows for questions on specific announcements.
  • For chat during virtual meetings, use #class-meetings-chat where possible.
    • It’s persistent across class meetings and breakout rooms.
    • I have another monitor with the channel open while sharing my screen.
  • For Homework 1, you’ll need to set up a course repository.
  • Check that @softsys-2022-01-instructors and @softsys-2022-01-assistant are collaborators with write access on your fork.
    • If not, add them with write access.

Stack Diagrams #

  • You may remember stack diagrams in Python.
  • They are a tool to show you what functions are running and what each variable is.
  • In C, things look similar, but differ from Python in a few ways.

Stack Diagram Exercise #

Draw a stack diagram just before the return z; line executes in add:

/* add: return the sum of x and y */
int add(int x, int y) {
    int z = x + y;
    return z;
} 

/* test_add: test add and print the result. */
void test_add() {
    int sum = add(3, 4);
    printf("%d\n", sum);
}

/* check_parity: 
return "n is even" if n is even,
and "n is odd" otherwise  
*/
char *check_parity(int n) {
    switch (n%2) {
    case 0:
        return "n is even";
    case 1:
        return "n is odd";
    }
}

void main() {
    test_add();

    char *s = check_parity(3);
    printf("%s\n", s);
}

See this example on C tutor

Linux Tutorial #

  • In systems work, it’s important to be comfortable working with UNIX (preferably Linux).
  • We’re going to spend some time doing a Linux tutorial.
  • As usual, collaborate in breakout rooms/Discord.
  • If you have your computational environment set up, work in the Terminal there.
  • Otherwise, make an account on https://repl.it and open a Bash repl.
  • Head to https://linuxjourney.com/
  • Do the “Command Line” tutorial in its entirety.
  • Do the “Text-Fu” tutorial through the end of Section 4.
  • Help others if you are done early.

Compilation #

  • Remember the steps of compilation:
    • Preprocessing
    • Parsing
    • Static checking
    • Code generation
    • Optimization
    • Linking
  • We’re going to do an exercise to explore these steps.
  • If you haven’t forked and cloned the course repo, do so now.
  • As usual, collaborate in breakout rooms/Discord.

Compilation Exercise #

In the course repository, cd into exercises/ex01 and load hello.c in the text editor of your choice. Then do the steps below. Feel free to explore as you go through these steps, and don’t worry about trying to finish everything.

1. Compile and Run #

Compile hello.c and run a.out.

Compile it so the executable is called hello, and run it.

2. Explore the Object File #

Compile hello.c using the -c flag, which generates object code. Use nm to see what functions are defined in hello.c, and which ones are used but not defined.

Define a new function, and add a reference to another function. Run gcc and nm again to see the effect.

Run the following command to find out where libc.a lives:

gcc --print-file-name=libc.a

Then use nm to find out what’s in libc.a.

3. Explore Assembly #

Compile hello.c using the -S flag, then load hello.s in a text editor. How much sense can you make of it?

Compile hello.s to generate a.out and run it.

4. Play with Assembly #

Modify hello.c to add these lines:

int a = 3;
int b = 4;
int c = a + b;
printf("c is %d\n", c);

Compile hello.c to get hello.s. What does the generated code look like?

Find the instruction addl and replace it with subl. Compile your modified version of hello.s and run it.

Compile hello.c again with -O2 and see what the generated code looks like. What happened to the addl?

5. Explore Compilation #

Add the following lines to hello.c, compile to hello.s, and load hello.s:

if (c % 2 == 0) {
    printf("c is even\n");
} else {
    printf("c is odd\n");
}

How much sense can you make of the assembly code? How does the modulus operator get compiled? What if you compute c % 3?

6. Explore the Switch Statement #

Rewrite the if statement using a switch, compile, and look at the assembly code.

What happens if you forget the break statements? Why do you think the default behavior of the switch statement is to fall through? See this article on fallthrough.

7. Explore the Preprocessor #

Run gcc on hello.c so it runs the preprocessor only. Use wc to count the lines in the output. Add a line to include stdlib.h as well as stdio.h, and run the preprocessor again.

Final Thoughts #

If you enjoyed these exercises, you might like this article: Understanding C by learning assembly

It might be a good (part of) Project 1.

For Next Time #

  • Read Head First C, Chapter 2.
  • Finish Homework 1.