Eroxl's Notes
03 - Dynamic Arrays and C Pointers (CPSC 213 Practice)

Problem 1

Compiling code that accesses an element of an array involves computing the base address of the array and the offset from that address to the specified element. The offset to array elements can sometimes be computed statically.

  • [x] (a) True
  • [ ] (b) False

Problem 2

Assume the following declaration (in C) of variable a.

int* a = (int[]) { 32, 24, 38, 21, 17, 12 };

Note that the syntax given above is available in modern C compilers, and is conceptually the same as the following, but more concise:

int* a = malloc(6 * sizeof(int));
a[0] = 32;
a[1] = 24;
a[2] = 38;
a[3] = 21;
a[4] = 17;
a[5] = 12;

For each of the following C expressions match with the value of the expression. If the expression is invalid, or the information provided is insufficient to compute the value, keep the value blank, and select the appropriate option.

&a[5] - &a[1]

  • [x] Expression is valid with known value
  • [ ] Insufficient information Expression is invalid (compilation error)
  • [ ] Expression is invalid (runtime error)

Evaluates to 4

&a[10] - &a[5]

  • [x] Expression is valid with known value
  • [ ] Insufficient information Expression is invalid (compilation error)
  • [ ] Expression is invalid (runtime error)

Evaluates to 5

&(*(a+(*(a+5)-11)))-&a[1]

  • [x] Expression is valid with known value
  • [ ] Insufficient information Expression is invalid (compilation error)
  • [ ] Expression is invalid (runtime error)
a+5 // &a[5]
*(a+5) // 12
*(a+5) - 11 // 1
a+(*(a+5)-11) // &a[1]
*(a+(*(a+5)-11)) // 24
&(*(a+(*(a+5)-11)))-&a[1] // 0

Evaluates to 0

Problem 3

Consider an array named a in C with the values { 15, 16, 17, 18, 19 } (the array may have additional unknown values, but these are the values at the start of the array). Consider a variable named i of type intĀ *, that points to the start of array a. Assume that i is stored at address 0x3200, and that a is stored at address 0x4600.

For each of the following C expressions match with the value of the expression. If the expression is invalid, or the information provided is insufficient to compute the value, keep the value blank, and select the appropriate option.

&i[0]:

  • [x] Expression is valid with known value
  • [ ] Insufficient information
  • [ ] Expression is invalid (runtime error)

Evaluates to 0x4600

i:

  • [x] Expression is valid with known value
  • [ ] Insufficient information
  • [ ] Expression is invalid (runtime error)

Evaluates to 0x4600

*i:

  • [x] Expression is valid with known value
  • [ ] Insufficient information
  • [ ] Expression is invalid (runtime error)

Evaluates to 15

*(i+1):

  • [x] Expression is valid with known value
  • [ ] Insufficient information
  • [ ] Expression is invalid (runtime error)

Evaluates to 16

*(i+9):

  • [ ] Expression is valid with known value
  • [x] Insufficient information
  • [ ] Expression is invalid (runtime error)

Problem 4

Consider the following C global variable declarations.`

int a, b, c, *d, **e, f[10], *g[10], **h[10];

For the C statement below, indicate the total number of memory locations accessed (i.e. read and/or written) when it executes. Do not count the loading of the instruction itself. Assume that nothing useful is stored in any register before the statement executes.

a = &b - &a;
  • reads/loads: 0
  • writes/stores: 1

Problem 5

.pos 0x100
    ld $a, r1
    ld (r1), r1
    ld $1,r2
    ld (r1,r2,4), r2
    ld (r1,r2,4), r3
    halt

.pos 0x1000
a: .long 0x2000
b: .long 0x2004

.pos 0x2000
    .long 0x6
    .long 0x5
    .long 0x2
    .long 0x4
    .long 0x3
    .long 0x5
    .long 0x5
    .long 0x2
    .long 0x6

(a). What is the Value in r3 after the Program Executes?

ld $a, r1 # &a
ld (r1), r1 # a
ld $1,r2 # 1
ld (r1,r2,4), r2 # a[1] -> 0x5
ld (r1,r2,4), r3 # a[5] -> 0x5

r3=0x5

(b). If the line ld $a, r1 Was Changed to ld $b, r1, what Would Be the Value in R3 after the Program Executes?

ld $a, r1 # &b
ld (r1), r1 # b <-> &a[1]
ld $1,r2 # 1
ld (r1,r2,4), r2 # b[1] -> 0x2
ld (r1,r2,4), r3 # b[3] -> 0x4

r3=0x4

Problem 6

Consider the following C global variable declaration.

int a;
int b[15];
int *c;
int **d;

Translate the following C statements into assembly language.

Pointers are 4-bytes long.

Use labels to refer to the memory address of each variable. Assume that these labels have already been defined; i.e., do not include their definition in your answer. Also, do not include any assembly directives such as .pos or .long.

You may add comments if it helps you (using the standard notation # comment), but doing so is not required.

Translate this C code

b[a] = c[a];

Into SM213 Assembly code

ld $a, r0 # &a
ld (r0), r1 # a

ld $c, r2 # &c
ld (r2), r3 # c

ld (r3, r1, 4), r4 # c[a]

ld $b, r5 # &b
ld (r5), r6 # b
st r4, (r5, r1, 4) # b[a] = c[a]

Problem 7

In this question you will analyze the execution of three short blocks of code based on a common set of variable declarations and initializations. This common code is included with each subquestion for convenience, but it is the same for every subquestion. Treat each subquestion separately; that is, each one starts from scratch from the initialized values of the variables.

For each question, give the following three values for the last line of each code block following the execution of the entire block:

  1. the memory address which that line writes to,
  2. the value that is written to that address, and
  3. the number of distinct memory locations read by that line.

If you cannot determine the memory address from the information given, enter 0 for the address.

When computing the number of distinct locations read, assume nothing about the value of registers prior to the execution of the last statement: count a location even if the previous line also read (or wrote) that location. If the line reads from a memory location multiple times, count it only once. Assume that memory accesses always succeed, i.e. that all memory addresses are accessible to the program.

For example, for the following code block:

int *foo = (int *)0x1000;
int *bar = (int *)0x1000;
*foo = 1;
*foo = *foo + *bar + 1;

you would answer address = 0x1000, value = 3 and locations = 3 (one for foo, one for bar, and one for what they point to).

Give memory addresses in hex; and values and location counts in decimal.

// Declarations and Initializations --- THE SAME FOR EVERY SUBQUESTION
int *i = (int *)0x7000;
int *p = (int *)0x7004;
int *t = (int *)0x7008;
int *y = (int *)0x700c;
int *z = (int *)0x6000;
int **b = (int **)0x9000;
int **k = &p;
int **s = &i;
int **u = &t;
int **w = &y;
*i = 20;
*p = 4;
*t = 20;
*y = 19;
// set b[0] ... b[9] = [&z[0], &z[1], ... , &z[9]]
// set z[0] ... z[9] = [7, 3, 8, 9, 1, 4, 6, 5, 2, 0]

(a)

// Unique Code for this Subquestion
t = p;
*t = *y + *t;
  • Address: 0x7004
  • Value: 23
  • Locations: 4

(b)

// Unique Code for this Subquestion
*y = *(z + 4);
b[*y] = *b + 6;
*b[*y] = *b[*y] + z[*y] + (&z[5] - &z[4]);
  • Address: 0x6018
  • Value: 10
  • Locations: 7