Eroxl's Notes
Assignment 3 - Dynamic Arrays & C Pointers

Problem 1

Consider the following C file:

#include <stdlib.h>
#include <stdio.h>

// YOU: Allocate these global variables, using these names
int  s, b;
int* d;
int  i[10];

int main (int argv, char** argc) {
  // Ignore this block of code
  if (argv != 11) {
    fprintf (stderr, "usage: i[0] ... i[9]\n");
    exit (EXIT_FAILURE);
  }
  for (int j=0; j<10; j++)
    i[j] = atol (argc[1 + j]);

  // YOU: Implement this code
  s  = i[5];
  s  = i[s];
  d  = &b;
  *d = 9;
  d  = &i[i[7]];
  *d = *d + i[1];

  // Ignore this block of code
  printf ("s=%d b=%d d=&i[%d] i={", s, b, d - i);
  for (int j=0; j<10; j++)
    printf("%d%s", i[j], j<9? ", ": "}\n");
}

Produce your own sm213 file, q1.s, that does what the highlighted lines in q1.c does; you do not need to translate the lines that are marked as ignored.

Note that you can run the C program, specifying input values on the command line to see what the program should do. In the simulator you will enter the inputs directly in the memory locations of variables, and you will examine the output the same way.

For example, to compile a C program named foo.c from the command line, you would type the following.

gcc -std=gnu11 -o foo foo.c

Note that -std=gnu11 selects the common gnu 11 dialect of C and that 11 is the number 11, not two lowercase L's.

And then to run the resulting executable you would type the following.

./foo

Remember that every line of your assembly file must have a comment. The comment will be manually evaluated by the TAs after the assignment deadline.

ld $s, r0 # r0 = &s

ld $i, r1 # r1 = &i
ld $5, r2 # r2 = 5

ld (r1, r2, 4), r3 # r3 = i[5]
st r3, (r0) # s = i[5]

ld (r1, r3, 4), r4 # r4 = i[s]
st r4, (r0) # s = i[s]

ld $d, r0 # r0 = &d
ld $b, r1 # r1 = &b
st r1, (r0) # d = &b

ld $9, r2 # r2 = 9
st r2, (r1) # *d = 9

ld $7, r2 # r2 = 7
ld $i, r3 # r3 = &i
ld (r3, r2, 4), r4 # r4 = i[7]
shl $2, r4 # r4 = i[7] * 4
add r3, r4 # r4 = &i + i[7] * 4
ld $d, r0 # r0 = &d
st r4, (r0) # d = &i + i[7] * 4

ld $i, r0 # r0 = &i
ld 4(r0), r1 # r1 = i[1]

ld $d, r2 # r2 = &d
ld (r2), r3  # r3 = d
ld (r3), r4  # r4 = *d

add r4, r1 # r4 = *d + i[1]
st r1, (r3) # *d = *d + i[1]

halt

.pos 0x2000
    s:      .long 0
    b:      .long 0
    d:      .long 0
    i:      .long 0
            .long 1
            .long 2
            .long 3
            .long 4
            .long 5
            .long 6
            .long 7
            .long 8
            .long 9

Problem 2

Consider the following C file:

#include <stdlib.h>
#include <stdio.h>

// YOU: Allocate these global variables, using these names
int  a[3];
int  s[5];
int  tos;
int  tmp;

int main (int argv, char** argc) {
  // Ignore this block of code
  if (argv != 4) {
    fprintf (stderr, "usage: a b c\n");
    exit (EXIT_FAILURE);
  }
  for (int k=0; k<3; k++)
    a[k] = atol (argc[1 + k]);
  for (int k=0; k<5; k++) s[k] = 0;

  // YOU: Implement this code
  tmp = 0;
  tos = 0;
  s[tos] = a[0];
  tos++;
  s[tos] = a[1];
  tos++;
  s[tos] = a[2];
  tos++;
  tos--;
  tmp = s[tos];
  tos--;
  tmp = tmp + s[tos];
  tos--;
  tmp = tmp + s[tos];

  // Ignore this block of code
  printf ("a[0]=%d a[1]=%d a[2]=%d\n", a[0],a[1],a[2]);
  printf ("tos=%d tmp=%d \n", tos, tmp);
  for (int k=0; k<5; k++)
    printf("s[%d]=%d, ",k,s[k]);
  printf("\n");
}

Produce your own sm213 file, q2.s, that does what the highlighted lines in q2.c does; you do not need to translate the lines that are marked as ignored.

Note that you can run the C program, specifying input values on the command line to see what the program should do. In the simulator you will enter the inputs directly in the memory locations of variables, and you will examine the output the same way.

Remember that every line of your assembly file must have a comment. The comment will be manually evaluated by the TAs after the assignment deadline.

ld   $0, r0          # r0 = 0
ld   $tmp, r1        # r1 = &tmp
st   r0, (r1)        # tmp = 0

ld   $tos, r2        # r2 = &tos
st   r0, (r2)        # tos = 0

ld   $s, r3          # r3 = &s
ld   $a, r4          # r4 = &a

# s[tos] = a[0];
ld   (r2), r5        # r5 = tos
ld   (r4, r5, 4), r6 # r6 = a[tos] = a[0]
st   r6, (r3, r5, 4) # s[tos] = a[0]

# tos++;
inc  r5              # r5 = r5 + 1
st   r5, (r2)        # tos = r5

# s[tos] = a[1];
ld   (r2), r5        # r5 = tos
ld   (r4, r5, 4), r6 # r6 = a[tos] = a[1]
st   r6, (r3, r5, 4) # s[tos] = a[1]

# tos++;
inc  r5              # r5 = r5 + 1
st   r5, (r2)        # tos = r5

# s[tos] = a[2];
ld   (r2), r5        # r5 = tos
ld   (r4, r5, 4), r6 # r6 = a[tos] = a[2]
st   r6, (r3, r5, 4) # s[tos] = a[2]

# tos++;
inc  r5              # r5 = r5 + 1
st   r5, (r2)        # tos = r5

# tos--;
ld   (r2), r5        # r5 = tos
dec  r5              # r5 = r5 - 1
st   r5, (r2)        # tos = r5

# tmp = s[tos];
ld   (r2), r5        # r5 = tos
ld   (r3, r5, 4), r6 # r6 = s[tos]
st   r6, (r1)        # tmp = s[tos]

# tos--;
ld   (r2), r5        # r5 = tos
dec  r5              # r5 = r5 - 1
st   r5, (r2)        # tos = r5

# tmp = tmp + s[tos];
ld   (r1), r6        # r6 = tmp
ld   (r2), r5        # r5 = tos
ld   (r3, r5, 4), r7 # r7 = s[tos]
add  r7, r6          # r6 = tmp + s[tos]
st   r6, (r1)        # tmp = r6

# tos--;
ld   (r2), r5        # r5 = tos
dec  r5              # r5 = r5 - 1
st   r5, (r2)        # tos = r5

# tmp = tmp + s[tos];
ld   (r1), r6        # r6 = tmp
ld   (r2), r5        # r5 = tos
ld   (r3, r5, 4), r7 # r7 = s[tos]
add  r7, r6          # r6 = tmp + s[tos]
st   r6, (r1)        # tmp = r6

halt

.pos 0x2000
     a:   .long 0  
          .long 0
          .long 0
     s:   .long 0
          .long 0
          .long 0
          .long 0
          .long 0
     tos: .long 0
     tmp: .long 0

Problem 3

Consider the following C file:

#include <stdlib.h>
#include <stdio.h>

// YOU: Allocate these global variables, using these names
int  a;
int* p;
int  b[5];

int main (int argv, char** argc) {
  // Ignore this block of code
  if (argv != 6) {
    fprintf (stderr, "usage: a b c d e\n");
    exit (EXIT_FAILURE);
  }
  for (int k=0; k<5; k++)
    b[k] = atol (argc[1 + k]);

  // YOU: Implement this code
  a = 3;
  p = &a;
  *p = *p - 1;

  p = &b[0];
  p++;
  p[a] = b[a];
  *(p+3) = b[0];

  // Ignore this block of code
  printf ("a=%d *p=%d\n", a, *p);
  for (int k=0; k<5; k++)
    printf("b[%d]=%d, ",k,b[k]);
  printf("\n");
}

Produce your own sm213 file, q3.s, that does what the highlighted lines in q3.c does; you do not need to translate the lines that are marked as ignored.

Note that you can run the C program, specifying input values on the command line to see what the program should do. In the simulator you will enter the inputs directly in the memory locations of variables, and you will examine the output the same way.

Remember that every line of your assembly file must have a comment. The comment will be manually evaluated by the TAs after the assignment deadline.

# a = 3
ld $a, r0                # r0 = &a
ld $3, r1                # r1 = 3
st r1, 0(r0)             # a = 3

# p = &a;
ld $p, r2                # r2 = &p
st r0, 0(r2)             # p = &a

# *p = *p - 1;
ld 0(r2), r3             # r3 = p
ld 0(r3), r4             # r4 = *p
dec r4                   # r4 = *p - 1
st r4, 0(r3)             # *p = *p - 1

# p = &b[0];
ld $b, r5                # r5 = &b[0]
st r5, 0(r2)             # p = &b[0]

# p++;
ld 0(r2), r5             # r5 = p
inca r5                  # r5 = p + 4
st r5, 0(r2)             # p = p + 1

# p[a] = b[a];
ld $a, r0                # r0 = &a
ld 0(r0), r6             # r6 = a
ld $b, r7                # r7 = &b[0]
ld (r7, r6, 4), r1       # r1 = b[a]
ld 0(r2), r5             # r5 = p
st r1, (r5, r6, 4)       # p[a] = b[a]

# *(p+3) = b[0];
ld 0(r7), r1             # r1 = b[0]
ld 0(r2), r5             # r5 = p
st r1, 12(r5)            # *(p+3) = b[0]

halt

.pos 0x2000
    a:      .long 0
    p:      .long 0
    b:      .long 0
            .long 0
            .long 0
            .long 0
            .long 0

Problem 4

#include <stdlib.h>
#include <stdio.h>

int val[4];

void sort (int n) {
  int t;
  for (int i=n-1; i>0; i--)
    for (int j=i-1; j>=0; j--)
      if (val[i] < val[j]) {
        t = val[i];
        val[i] = val[j];
        val[j] = t;
      }
}

int main (int argc, char** argv) {
  char* ep;
  int   n;
  n = argc - 1;
  if (n > 4) {
    fprintf (stderr, "Static limit of 4 numbers\n");
    return -1;
  }
  for (int i=0; i<n; i++) {
    val[i] = strtol (argv[i+1], &ep, 10);
    if (*ep) {
      fprintf (stderr, "Argument %d is not a number\n", i);
      return -1;
    }
  }
  sort (n);
  for (int i=0; i<n; i++)
    printf ("%d\n", val[i]);
}

You were presented with the program exchange_sort_static.c that reads four elements from the command-line arguments and sorts them using the Exchange-Sort algorithm. Create a new C program named exchange_sort_dynamic.c that removes the static-array limitation of the original version. The only change you need to make is to turn val into a dynamic array and to allow the program to sort arbitrary lists of integers provided on the command lines (e.g. more than 4).

Recall that you need to allocate dynamic arrays dynamically by calling the procedure malloc. For example to allocate an array of 10 shorts you say:

short *s = malloc (10 * sizeof(*s));

Make sure to test your program. Note that the autograding test below will be reviewed by a TA before your grade is final.

#include <stdlib.h>
#include <stdio.h>

int *val;

void sort (int n) {
  int t;
  for (int i=n-1; i>0; i--)
    for (int j=i-1; j>=0; j--)
      if (val[i] < val[j]) {
        t = val[i];
        val[i] = val[j];
        val[j] = t;
      }
}

int main (int argc, char** argv) {
  char* ep;
  int   n;
  
  n = argc - 1;
  val = malloc (n * sizeof(int));

  for (int i=0; i<n; i++) {
    val[i] = strtol (argv[i+1], &ep, 10);
    if (*ep) {
      fprintf (stderr, "Argument %d is not a number\n", i);
      return -1;
    }
  }

  sort(n);
  
  for (int i=0; i<n; i++) printf ("%d\n", val[i]);

  free(val);
}

Problem 4

In the previous question you created a program called exchange_sort_dynamic.c that reads an unlimited number of elements from the command-line arguments and sorts them using the Exchange-Sort algorithm.

Now, create another C program called exchange_sort_awesome.c that extends your earlier work. This program must not include any square brackets anywhere (including comments!). All access to the arrays must be made using pointer arithmetic and the dereference operator (i.e., *).

Make sure to test your program. Note that the autograding test below will be reviewed by a TA before your grade is final.

#include <stdlib.h>
#include <stdio.h>

int *val;

void sort (int n) {
  int t;
  for (int i=n-1; i>0; i--) {
    for (int j=i-1; j>=0; j--) {
      int valA = *(val + i);
      int valB = *(val + j);

      if (valA < valB) {
        t = valA;
        *(val + i) = valB;
        *(val + j) = t;
      }
    }
  }
}

int main (int argc, char** argv) {
  char* ep;
  int   n;
  
  n = argc - 1;
  val = malloc (n * sizeof(int));

  for (int i=0; i<n; i++) {
    *(val + i) = strtol (*(argv+i+1), &ep, 10);
    if (*ep) {
      fprintf (stderr, "Argument %d is not a number\n", i);
      return -1;
    }
  }

  sort(n);
  
  for (int i=0; i<n; i++) printf ("%d\n", *(val + i));

  free(val);
}

Problem 5

Let array a be declared and initialized like this:

int a[10] = { 22, 31, 16, 36, 44, 10, 24, 42, 49, 42 };

What is the value of: *(a + 7)?

42

What is the value of: &a[5] - &a[4]?

1

What is the value of: *(a + (&a[1] - a + 4))?

&a[1] - a + 4           // 5
*(a + (&a[1] - a + 4))  // a[5]
*(a + (&a[1] - a + 4))  // 10
10
10