CPSC 355: Tutorial 9
Arrays, Multidimensional Arrays
PhD Student
Fall 2017
Outline
- Assignment 2
- Linear arrays (with this, you should be able to finish assignment 3)
- Multidimensional Arrays
Assignment 2
#include <stdio.h>
int main()
{
int multiplier, multiplicand, result_high, result_low, i, negative;
long int result, temp1, temp2;
multiplicand = -8192;
multiplier = 99;
result_high = 0;
printf("multiplier = 0x%08x (%d) multiplicand = 0x%09x (%d) \n\n",
multiplier, multiplier, multiplicand, multiplicand);
negative = multiplier < 0 ? 1 : 0;
for(i = 0; i < 32; i++) {
if(multiplier & 1) {
result_high = result_high + multiplicand;
}
multiplier = multiplier >> 1;
if(result_high & 1) {
multiplier = multiplier | 0x80000000;
} else {
multiplier = multiplier & 0x7FFFFFFF;
}
result_high = result_high >> 1;
}
if(negative) {
result_high = result_high - multiplicand;
}
printf("result_high = 0x%08x, result_low = 0x0%08x\n", result_high, result_low);
temp1 = (long int) result_high;
temp1 = temp1 << 32;
temp2 = (long int) multiplier & 0xFFFFFFFF;
result = temp1 + temp2;
printf("64-bit result: 0x%016lx (%ld)\n", result, result);
}
Assignment 2
#include <stdio.h>
int main()
{
int multiplier, multiplicand, result_high, result_low, i, negative;
long int result, temp1, temp2;
multiplicand = -8192;
multiplier = 99;
result_high = 0;
printf("multiplier = 0x%08x (%d) multiplicand = 0x%09x (%d) \n\n",
multiplier, multiplier, multiplicand, multiplicand);
// Didn't do this...
// negative = multiplier < 0 ? 1 : 0;
for(i = 0; i < 32; i++) {
if(multiplier & 1) {
result_high = result_high + multiplicand;
}
multiplier = multiplier >> 1;
if(result_high & 1) {
multiplier = multiplier | 0x80000000;
} else {
multiplier = multiplier & 0x7FFFFFFF;
}
result_high = result_high >> 1;
}
// Did it here instead
if(multiplier < 0) {
result_high = result_high - multiplicand;
}
printf("result_high = 0x%08x, result_low = 0x0%08x\n", result_high, result_low);
temp1 = (long int) result_high;
temp1 = temp1 << 32;
temp2 = (long int) multiplier & 0xFFFFFFFF;
result = temp1 + temp2;
printf("64-bit result: 0x%016lx (%ld)\n", result, result);
}
Assignment 2
Why is this incorrect?
The value of multiplier changes throughout the loop.
See tutorial 6 for a less complicated version of the code.
Linear Arrays
#include <stdio.h>
#define ARRAY_SIZE 10
int main(int argc, char *argv[]) {
unsigned long sum = 0;
unsigned int i = 0;
unsigned int array[ARRAY_SIZE];
for(i = 0; i < ARRAY_SIZE; i++) {
array[i] = rand();
}
for(i = 0; i < ARRAY_SIZE; i++) {
sum = array[i] + sum;
printf("array[%i] = %i (sum = %li)\n", i, array[i], sum);
}
return 0;
}
An array is really just a contiguous sequence of variables.
Let's start off with an example
Linear Arrays
Let's think about how our stack should look (each cell is 8 bytes)
Free memory |
old stack |
$sp
Free memory |
x29 (old $fp) |
x30 (old $lr) |
sum variable |
i variable, array[0] |
array[1], array[2] |
... |
array[9], ??? |
old stack |
$sp
Linear Arrays
Free memory |
x29 ($fp) |
x30 ($lr) |
sum variable |
i variable, array[0] |
array[1], array[2] |
... |
array[9], ??? |
old stack |
$sp
We need 16 bytes for fp and lr, 16 for sum and i (although we'll only use 12 of those) and 10 * 4 bytes for the array.
We need 72 bytes in total -- or 80 bytes when rounded up to the 16 byte stack boundary
stp fp, lr, [sp, -80 & -16]!
mov fp, sp
$fp
Linear Arrays
// File: tut8ex1.asm
// Description: Sums a random list of numbers
// Define the size of the array
array_count = 10
// Define the sizes of the variables on the stack
array_size = array_count * 4 // 4 bytes for an integer
i_size = 4 // 4 bytes int
sum_size = 8 // 8 bytes for a long
// Define the offsets from the frame pointer
sum_so = 16
i_so = sum_so + sum_size
array_so = i_so + i_size
// Sum up all the sizes
var_size = array_size + i_size + sum_size
alloc = -(16 + var_size) & -16
dealloc = -alloc
fp .req x29
lr .req x30
fmt1: .string "array[%i] = %i (sum = %li)\n"
.balign 4
.global main
main:
stp fp, lr, [sp, alloc]!
mov fp, sp
// more code...
mov w0, 0 // setup 0 return code
ldp fp, lr, [sp], dealloc
ret
Free memory |
x29 ($fp) |
x30 ($lr) |
sum variable |
i variable, array[0] |
array[1], array[2] |
... |
array[9], ??? |
old stack |
$fp
Linear Arrays
#include <stdio.h>
#define ARRAY_SIZE 10
int main(int argc, char *argv[]) {
unsigned long sum = 0;
unsigned int i = 0;
unsigned int array[ARRAY_SIZE];
for(i = 0; i < ARRAY_SIZE; i++) {
array[i] = rand();
}
for(i = 0; i < ARRAY_SIZE; i++) {
sum = array[i] + sum;
printf("array[%i] = %i (sum = %li)\n", i, array[i], sum);
}
return 0;
}
Linear Arrays
main:
stp fp, lr, [sp, alloc]! // Allocate stack vars, save fp lr
mov fp, sp // save stack frame
str wzr, [fp, i_so] // set i = 0
str xzr, [fp, sum_so] // set sum = 0
loop_1_top:
bl rand // Generate a random number, put it in w0
ldr w1, [fp, i_so] // load i into w1
add x2, fp, array_so // set x2 to the address of the first element of the array
str w0, [x2, w1, SXTW 2] // store w0 (random number) into address x2 + signext(w1) << 2
// remember x2 = fp + array_os, and w1 << 2 = i * 4
// thus this is equivalent to "store x0 in the i'th
// element of the array".
ldr w1, [fp, i_so] // load i
add w1, w1, 1 // increment i
str w1, [fp, i_so] // store i
cmp w1, array_count // if i < array count
b.lt loop_1_top
// second loop in next slide
mov w0, 0 // setup 0 return code
ldp fp, lr, [sp], dealloc
ret
Linear Arrays
#include <stdio.h>
#define ARRAY_SIZE 10
int main(int argc, char *argv[]) {
unsigned long sum = 0;
unsigned int i = 0;
unsigned int array[ARRAY_SIZE];
for(i = 0; i < ARRAY_SIZE; i++) {
array[i] = rand();
}
for(i = 0; i < ARRAY_SIZE; i++) {
sum = array[i] + sum;
printf("array[%i] = %i (sum = %li)\n", i, array[i], sum);
}
return 0;
}
Linear Arrays
// ....
b.lt loop_1_top
str wzr, [fp, i_so] // set i var to 0
loop_2_top:
ldr w1, [fp, i_so] // load i into w1
add x2, fp, array_so // set x2 to the address of the first element of the array
ldr w3, [x2, w1, SXTW 2] // load from address x2 + signext(w1) << 2
// remember x2 = fp + array_os, and w1 << 2 = i * 4
// thus this is equivalent to "the i'th
// element of the array".
ldr x4, [fp, sum_so] // load the sum variable
add x4, x4, x3 // Don't sign extend w3, just take its wider reg x3
str x4, [fp, sum_so] // place x4 back in the sum var
// printf as usual
ldr x0, =fmt1
ldr w1, [fp, i_so] // first arg = i
ldr w2, [x2, w1, SXTW 2] // second arg = array[i]
ldr x3, [fp, sum_so] // third arg = sum
bl printf
ldr w1, [fp, i_so] // load i
add w1, w1, 1 // increment i
str w1, [fp, i_so] // store i
cmp w1, array_count // if i <= array count
b.lt loop_2_top
mov w0, 0 // setup 0 return code
ldp fp, lr, [sp], dealloc
ret
Multidimensional Arrays
This isn't as scary as it sounds, for example here's a 2D array
We want to store values to cells in this array
x=1
y=2
42
If a value represents, say, shade...
Multidimensional Arrays
This isn't as scary as it sounds, for example here's a 2D array
Then you just have (a black and white, and uncompressed) image
Multidimensional Arrays
Let's just turn this into a linear array
x
y
0 | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 |
45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 |
0 |
1 |
2 |
3 |
... |
58 |
2D
Linear
Multidimensional Arrays
How do I index the linear array given (x,y) pairs?
x
y
0 | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 |
45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 |
0 |
1 |
2 |
3 |
... |
58 |
(2, 0) = cell 2
Multidimensional Arrays
How do I index the linear array given (x,y) pairs?
x
y
0 | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 |
45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 |
0 |
... |
8 |
9 |
... |
58 |
(2, 1) = cell 7 + 2 = cell 9
Multidimensional Arrays
How do I index the linear array given (x,y) pairs?
x
y
0 | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 |
45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 |
0 |
... |
15 |
16 |
... |
58 |
(2, 2) = cell 14 + 2 = cell 16
Multidimensional Arrays
How do I index the linear array given (x,y) pairs?
x
y
0 | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 |
45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 |
0 |
... |
15 |
16 |
... |
58 |
(x, y) = cell y*7 + x
Multidimensional Arrays
For a grid with a known grid_width
x
y
(x, y) = y*grid_width + x
Multidimensional Arrays
#include<stdio.h>
#define WIDTH 7
#define HEIGHT 7
int linear_index(int x, int y) {
return y * WIDTH + x;
}
int main(int argc, char *argv) {
char arr[WIDTH * HEIGHT];
// clear out the array
for(int j = 0; j < HEIGHT; j++)
for(int i = 0; i < WIDTH; i++)
arr[linear_index(i,j)] = ' ';
// left right eye
arr[linear_index(2,1)] = '|';
arr[linear_index(2,2)] = '|';
arr[linear_index(4,1)] = '|';
arr[linear_index(4,2)] = '|';
arr[linear_index(1,4)] = '\\';
arr[linear_index(2,5)] = '-';
arr[linear_index(3,5)] = '-';
arr[linear_index(4,5)] = '-';
arr[linear_index(5,4)] = '/';
// print array
for(int j = 0; j < HEIGHT; j++){
for(int i = 0; i < WIDTH; i++){
putchar(arr[linear_index(i,j)]);
}
putchar('\n');
}
return 0;
}
Multidimensional Arrays
This technique works up to n-dimensions
For example, if we have a 4 by 5 by 6 grid, and we want to find the linear index of (1,2,3)
Next Day
Work day, bring your questions!
CPSC 355: Tutorial 9
By Joshua Horacsek
CPSC 355: Tutorial 9
- 1,946