CSSE 132 Mini-reading · Exam preparation

Exam 1 Review: Reason Through Numbers, Memory, and Code

Use this review to connect the current course topics and practice explaining your reasoning on paper. Work through one section at a time; follow its resource links when you need more practice.

Why This Matters

One bit pattern can be a number, part of an address, or an instruction. Knowing which interpretation applies lets you connect C expressions, memory pictures, and ARM64 code. Practice showing intermediate steps: an explanation helps you catch mistakes that a final answer alone can hide.

1. Numbers: Bits, Bases, and Signed Values

Core idea: A byte contains 8 bits. Each hex digit represents 4 bits, so two hex digits represent one byte. An unsigned n-bit value ranges from 0 through 2n − 1. For two’s complement, the highest bit has weight −2n−1; the other bits keep their positive weights.

On paper: Convert between bases, keep the specified width, and explain how signed and unsigned interpretations differ.

Use place values

0x6D = 0110 1101₂
     = 6 × 16 + 13
     = 109₁₀

The grouping checks the hex conversion; place values check the decimal result.

Check a negative value

8-bit signed: 1110 1011₂
= −128 + 64 + 32 + 8 + 2 + 1
= −21

To encode −21, start with 0001 0101, invert all eight bits, and add one: 1110 1010 + 1 = 1110 1011.

Common mistakes: Dropping leading zeros changes the stated width. A leading 1 means negative only when the value is interpreted as signed. There are 256 eight-bit patterns, but the largest unsigned eight-bit value is 255.

Practice: Data Representation, Worksheet 02, Homework 1.

2. Addresses, Offsets, and Endianness

Core idea: In the course’s byte-addressable model, each address selects one byte. An n-bit address has 2n possible patterns. For a multi-byte value, endianness determines which byte goes at the lowest address.

On paper: Label consecutive byte addresses, split a value into bytes, and calculate capacity or an element’s byte offset.

Place two bytes in memory

A 16-bit value 0x4A91 begins at address 0x300:

Byte order0x3000x301
Little endian0x910x4A
Big endian0x4A0x91

The number stays the same; its byte placement changes. A 10-bit byte-addressable space contains 210 = 1024 bytes, with addresses 0 through 1023.

Common mistakes: Reverse bytes, not individual bits within a byte. Keep address capacity separate from installed memory. In capacity calculations, state whether a large unit uses powers of two.

Practice: Memory Addresses, Worksheet 03, Homework 2 addressing exercise.

3. Read C Expressions and Functions

Core idea: Declarations give variables types; statements change values. A function receives argument values and may return a value. Compilation translates C to assembly, assembly produces object code, and linking combines object code into an executable.

On paper: Trace assignments in order, distinguish comparison from assignment, and match output formats to values.

Trace before printing

int count = 11;
int groups = count / 4;
int leftover = count % 4;
printf("%d %d\n", groups, leftover);

Integer division gives 2 whole groups; the remainder is 3. The output is 2 3. %d prints an int; %c prints a character and %s prints a null-terminated string.

Common mistakes: = assigns; == compares. A character uses single quotes; a string uses double quotes. Updating a function’s local int parameter does not update the caller’s original variable.

Practice: C Programming Basics, Worksheet 06, Lab 2: Linux.

4. Arrays, Pointers, Strings, and Structs

Core idea: A pointer stores an address; dereferencing accesses the object there. Pointer arithmetic advances by the pointed-to type’s size. A C string ends at '\0'. A struct groups fields, which can include padding between them.

On paper: Distinguish an address from its contents, calculate array offsets, count string storage, and choose dot or arrow for field access.

Calculate an offset

If a four-byte int array starts at 0x500, its element with index 3 starts at 0x500 + 3 × 4 = 0x50C. The index counts elements; the offset counts bytes.

char label[] = "oak";

This array has four bytes: three letters and the terminator. Its string length is three.

Choose the field operator

struct point { int row; int col; };
struct point spot = {2, 6};
struct point *location = &spot;

spot.col, location->col, and (*location).col access the same field. A pointer’s size depends on the platform, not the size of the object it points to.

Common mistakes: p and *p mean different things. Indexing begins at zero. Use . for a struct object and -> for a pointer to one; do not assume every struct size is just the sum of its field sizes.

Practice: Pointers and Arrays, Strings and Structs, Worksheet 07, Worksheet 08.

5. ARM64 Registers, Arithmetic, Loads, and Stores

Core idea: wN is the lower 32-bit view of xN. Writing wN clears the upper 32 bits of xN. In our examples, ints use w registers and pointers use x registers.

On paper: Track source and destination registers, identify the accessed address, and distinguish a load from a store.

Separate register changes from memory changes

Suppose x4 holds an int array’s base address, and its second element contains 14.

ldr w6, [x4, #4]
sub w7, w6, #3
str w7, [x4, #8]

The load reads the second element into w6. Subtraction puts 11 in w7. The store writes 11 into the third element. Neither operation moves the base address in x4.

Common mistakes: The destination comes first in arithmetic. ldr w6, [x4] loads four bytes of data using a 64-bit address; it does not load the address itself. Avoid old ARM32 rN notation.

Practice: Assembly Basics, Worksheet 04, Homework 2 register-width and assembly tasks.

6. Comparisons, Branches, and Tracing

Core idea: cmp sets condition flags without changing its input registers. A conditional branch reads those flags; an unconditional b always jumps to its label.

On paper: Follow the executed path rather than reading every line as if it runs. Record values after each change.

Trace a short loop

mov w5, #6
.REPEAT:
sub w5, w5, #2
cmp w5, #0
bgt .REPEAT

The values after subtraction are 4, 2, then 0. The branch is taken twice; it is not taken after the comparison with zero. The body executes three times.

Common mistakes: A label is not an instruction. A loop’s exit condition may be the opposite of its C continuation condition. Do not change a value merely because cmp mentions it.

Practice: ARM64 Control Flow, Worksheet 05, Homework 3 assembly practice.

7. Function Arguments, Return Values, and Return Addresses

Core idea: For the simple functions studied in class, the first int argument uses w0, the second uses w1, and an int return value uses w0. Pointer arguments use the corresponding x register. bl saves the next instruction’s address in x30 and branches; ret returns through that saved address.

On paper: Identify values versus pointers, track an argument into a function, and distinguish the return value from the return address.

Read a leaf function

// int lower_by_two(int amount)
lower_by_two:
  sub w0, w0, #2
  ret

If its caller passes 9 in w0, subtracting two produces 7. The returned int is in w0; x30 identifies where execution resumes. A function making another call must preserve its own return address before that call overwrites x30.

Common mistakes: b does not save a return address. x30 holds a code address, not the function’s numeric result. Passing an int and passing its address are different.

Practice: Stack and Procedure Calls, Worksheet 10, Lab 3: Function Calls with GDB.

8. Memory Hierarchy and Tradeoffs

Core idea: Registers, cache, main memory, and storage serve different purposes. Compare access speed, cost per byte, capacity, and whether data survives loss of power.

On paper: Explain a tradeoff and calculate a weighted access time when a cache strategy is specified.

Separate working memory from saved files

When you edit a document, DRAM holds data the running program uses frequently. Its fast access helps the CPU keep working. The saved document lives on nonvolatile storage such as an SSD, so it remains available after shutdown. An SSD is fast compared with a hard disk, but much slower than DRAM for active working-memory accesses. You do not need to memorize exact timings to explain this difference.

PropertyDRAMSSD
Typical roleActive working dataSaved files and programs
Access speedMuch fasterSlower than DRAM
Without powerContents are lost (volatile)Contents persist (nonvolatile)
Cost and capacityTypically higher cost per GBTypically more storage for the same budget

Explain, then compare: Name a property and connect it to the job the device does. Speed, persistence, and cost per byte are different properties. “Volatile” and “loses data without power” are two descriptions of one property. Capacity depends on the device and budget, not a rule that DRAM can never hold large amounts of data.

Use the stated cache model

Suppose a cache lookup takes 3 ns, the hit rate is 80%, and a miss requires an additional 40 ns memory access. Every request pays the lookup cost:

average = 0.80 × 3 + 0.20 × (3 + 40)
        = 3 + 0.20 × 40 = 11 ns

For a large saved photo collection, nonvolatile storage keeps files after shutdown; DRAM serves active program data. Capacity and persistence matter as well as speed.

Common mistakes: A hit rate is a probability, not a time. Check whether a stated miss time includes the lookup. Faster memory does not automatically replace every other layer.

Practice: Memory Hierarchy, Worksheet 09, Homework 3 hierarchy and cache exercises.

Linux Commands: Find, Select, and Test

Use the terminal on your CSSE132 Linux VM to navigate, inspect files, build, and debug. Review Lab 2: Linux and its mystery cheatsheet for commands and pipes; revisit Lab 3 for GDB practice.

CommandWhat it does
pwdPrint your current directory.
lsList entries in the current directory.
cd exercises / cd ..Enter a directory / move to its parent.
head -n 8 practice.txtPrint the first eight lines.
tail -n 2 practice.txtPrint the last two lines.
grep 'maple' notes.txtPrint lines containing the text maple.

Worked example: select a line with a pipe

head -n 8 practice.txt | tail -n 1

head produces lines 1–8. The pipe | sends that output to tail, which keeps its final line. The result is only line 8 of practice.txt. Here tail reads the piped text; it does not read the original file again.

Contents versus position: grep 'maple' notes.txt searches for a value in the contents, wherever it occurs. It does not select a numbered line. Use grep -n 'maple' notes.txt to also display matching line numbers. Plain grep matches text within a line; grep -x 'maple' notes.txt requires the entire line to match.

Build, run, and debug

make
./practice_runner
gdb ./practice_runner

Run make in the directory containing the provided Makefile. If it defines a named target, use make target_name. Read the instructions to find the executable name; ./ runs it from the current directory. Check the test summary, not just whether it ran.

In GDB, break main sets a breakpoint; run starts execution; next steps over a source line; step enters a called function; print total inspects a variable; continue resumes execution; and quit exits. Build with debug information as provided by the course Makefile.

Two quick self-checks

  1. Which original file lines does head -n 7 practice.txt | tail -n 2 print?
  2. A file has 42 on line 5 and 142 on line 9. Does grep '42' values.txt select line 42? Which lines match, and how would you match only the line whose complete contents are 42?
Show Linux practice answers
  1. Lines 6 and 7: take the first seven, then the last two of that output.
  2. It searches contents, not line numbers. Both lines 5 and 9 match because both contain the text 42. Use grep -x '42' values.txt for the whole-line match.

Quick Reference

TaskStarting point
Signed n-bit range−2n−1 through 2n−1 − 1
Array element addressbase + index × element size
Little endianLeast significant byte at lowest address
Load / storeMemory → register / register → memory
Call / returnbl saves next address; ret resumes there

Check Yourself

Try these fresh practice prompts before opening the answers.

  1. Convert 0x35 to eight-bit binary and decimal.
  2. Interpret 1111 0110 as an eight-bit signed value.
  3. A four-byte int array begins at 0x640. Where does index 2 begin?
  4. In the loop above, change the initial value to 8. How many times does the body execute?
  5. A function returns an int to its caller. Which register communicates that value, and what different job does x30 perform?
Show practice answers
  1. 0011 0101; 3 × 16 + 5 = 53.
  2. −10: −128 + 64 + 32 + 16 + 4 + 2 = −10.
  3. 0x648: add 2 × 4 = 8 bytes.
  4. Four times: 6, 4, 2, 0 after subtraction.
  5. w0 communicates the int result; x30 holds the return address.

Prepare for the Paper Exam

Start with a blank sheet. Do conversions without a converter, draw byte addresses, and trace code using a small register table. Then check your work against the linked readings and worksheets. For each mistake, explain why the correct result makes sense and try a different example. Use the posted practice paper as broader practice, not as a prediction of the exam’s question layout.

  • I can show conversion steps and check signed values at a stated width.
  • I can calculate byte addresses and draw either byte order.
  • I can explain C expressions, pointer operations, and field access.
  • I can track registers and memory separately, following branches by hand.
  • I can distinguish function arguments, results, and return addresses.
  • I can explain memory tradeoffs and recognize common mistakes.