320 likes | 519 Views
Arrays and Pointers . Assembly: Arrays and structures CSCi 2021: Computer Architecture and Organization. Chap. 3.8 – 3.9. Today. Arrays One-dimensional Multi-dimensional (nested) Multi-level Structures Alignment Skipping some of the slides – on your own Exam rationale.
E N D
Assembly: Arrays and structuresCSCi 2021: Computer Architecture and Organization Chap. 3.8 – 3.9
Today • Arrays • One-dimensional • Multi-dimensional (nested) • Multi-level • Structures • Alignment Skipping some of the slides – on your own Exam rationale
Array Allocation • Basic Principle TA[L]; • Array of data type T and length L • Contiguously allocated region of L * sizeof(T) bytes char string[12]; x x + 12 int val[5]; x x + 4 x + 8 x + 12 x + 16 x + 20 double a[3]; x x + 8 x + 16 x + 24 char *p[3]; x x + 4 x + 8 x + 12
1 5 2 1 3 Array Access • Basic Principle TA[L]; • Array of data type T and length L • Identifier A can be used as a pointer to array element 0: Type T* int val[5]; x x + 4 x + 8 x + 12 x + 16 x + 20
1 5 2 1 3 Array Access • Basic Principle TA[L]; • Array of data type T and length L • Identifier A can be used as a pointer to array element 0: Type T* • Reference Type Value val[4] int3 valint * x val+1 &val[2] val[5] *(val+1) val + i int val[5]; x x + 4 x + 8 x + 12 x + 16 x + 20
1 9 0 5 4 2 7 2 1 1 3 2 0 3 9 Array Example #define ZLEN 5 typedefintzip_dig[ZLEN]; zip_digcmu = { 1, 5, 2, 1, 3 }; zip_digmit = { 0, 2, 1, 3, 9 }; zip_digucb = { 9, 4, 7, 2, 0 }; • Declaration “zip_dig cmu” equivalent to “int cmu[5]” • Example arrays were allocated in successive 20 byte blocks • Not guaranteed to happen in general zip_dig cmu; zip_dig mit; 56 36 16 40 60 20 64 24 44 68 28 48 52 32 72 56 36 76 zip_digucb;
1 5 2 1 3 Array Accessing Example • Register %edx contains starting address of array • Register %eax contains array index • Desired digit at 4*%eax + %edx • Use memory reference (%edx,%eax,4) zip_dig cmu; int get_digit (zip_dig z, int dig) { return z[dig]; } 16 20 24 28 32 36 IA32 # %edx = z # %eax = dig movl (%edx,%eax,4),%eax # z[dig]
Array Loop Example (IA32) void zincr(zip_dig z) { inti; for (i = 0; i < ZLEN; i++) z[i]++; // vs. z++; } # edx = z movl $0, %eax # %eax = i .L4: # loop: addl $1, ? # z[i]++ addl $1, ? # i++ cmpl $5, ? # i:5 ? # if !=, goto loop
Array Loop Example (IA32) void zincr(zip_dig z) { inti; for (i = 0; i < ZLEN; i++) z[i]++; // vs. z++; } # edx = z movl $0, %eax # %eax = i .L4: # loop: addl $1, (%edx,%eax,4) # z[i]++ addl $1, %eax # i++ cmpl $5, %eax # i:5 jne .L4 # if !=, goto loop
2 1 1 1 1 5 5 5 5 2 2 2 2 1 0 1 7 3 1 6 Nested Array/2D Example #define PCOUNT 4 zip_digpgh[PCOUNT] = {{1, 5, 2, 0, 6}, {1, 5, 2, 1, 3 }, {1, 5, 2, 1, 7 }, {1, 5, 2, 2, 1 }}; • “zip_dig pgh[4]” equivalent to “int pgh[4][5]” • Variable pgh: array of 4 elements, allocated contiguously • Each element is an array of 5 int’s, allocated contiguously • “Row-Major” ordering of all elements guaranteed zip_dig pgh[4]; 76 96 116 136 156
A[0][0] • • • A[0][C-1] • • • • • • • • • A [0] [0] A [R-1] [0] • • • A [1] [0] • • • • • • A [1] [C-1] A [R-1] [C-1] A [0] [C-1] A[R-1][0] • • • A[R-1][C-1] Multidimensional (Nested) Arrays • Declaration TA[R][C]; • 2D array of data type T • R rows, C columns • Type T element requires K bytes • Array Size • R * C * K bytes • Arrangement • Row-Major Ordering int A[R][C]; 4*R*C Bytes
A[0] A[i] A[R-1] • • • • • • A [R-1] [0] A [0] [0] • • • A [i] [0] A [0] [C-1] A [R-1] [C-1] A [i] [C-1] Nested Array Row Access • Row Vectors • A[i] is array of C elements • Each element of type T requires K bytes • Starting address A +i * (C * K) int A[R][C]; • • • • • • A+i*C*4 A+(R-1)*C*4 A
A[0] A[i] A[R-1] • • • • • • • • • A [R-1] [0] • • • A [0] [0] A [i] [j] A [0] [C-1] A [R-1] [C-1] Nested Array Row Access • Array Elements • A[i][j]is element of type T, which requires K bytes • Address A +i* (C * K)+ j * K = A + (i * C + j)* K row col int A[R][C]; • • • • • • A A+i*C*4 A+(R-1)*C*4 A+i*C*4+j*4
n X n Matrix Access – On Your Own • Array Elements • Address A +i* (C * K)+ j * K • C = n, K = 4 /* Get element a[i][j] */ int var_ele(int n, int a[n][n], int i, int j) { return a[i][j]; } movl 8(%ebp), %eax # n sall $2, %eax # n*4 movl %eax, %edx # n*4 imull 16(%ebp), %edx # i*n*4 movl 20(%ebp), %eax # j sall $2, %eax # j*4 addl12(%ebp), %eax # a + j*4 movl (%eax,%edx), %eax # *(a + j*4 + i*n*4)
0 9 1 4 5 2 7 2 1 3 2 1 3 0 9 univ 36 160 136 164 256 168 Multi-Level Array Example • Variable univ denotes array of 3 elements • Each element is a pointer • 4 bytes • Each pointer points to array of int’s zip_dig cmu = { 1, 5, 2, 1, 3 }; zip_dig mit = { 0, 2, 1, 3, 9 }; zip_dig ucb = { 9, 4, 7, 2, 0 }; #define UCOUNT 3 int *univ[UCOUNT] = {mit, cmu, ucb}; cmu 16 256 136 140 20 260 24 264 144 28 148 268 272 32 152 36 276 156 mit ucb Compare tointuniv[UCOUNT][5]? – need not be contiguous!
Array Element Accesses Multi-level array Nested array int get_pgh_digit (int index, int dig) { return pgh[index][dig]; } int get_univ_digit (int index, int dig) { return univ[index][dig]; } Accesses looks similar in C, but addresses very different: Mem[Mem[univ+4*index]+4*dig] Mem[pgh+20*index+4*dig]
Today • Arrays • One-dimensional • Multi-dimensional (nested) • Multi-level • Structures • Allocation • Access • Alignment
Today • Structures • Allocation • Access • Alignment • Instruction set architectures • Y86 • RISC/CISC
Structure Allocation structrec { inta[3]; inti; structrec *n; }; Memory Layout • Concept • Contiguously-allocated region of memory • Refer to members within structure by names • Members may be of different types a i n 20 12 0 16
Structure Access r r+12 structrec { inta[3]; inti; structrec *n; }; • Accessing Structure Member • Pointer indicates first byte of structure • Access elements with offsets a i n 20 12 0 16 IA32 Assembly void set_i(structrec *r, intval) { r->i = val; // or (*r).i = val; } # %edx= val # %eax= r movl %edx, 12(%eax) # Mem[r+12] = val
Structures & Alignment struct S1 { char c; inti[2]; double v; } *p; c i[0] i[1] v p p+1 p+5 p+9 p+17 c 3 bytes i[0] i[1] 4 bytes v p+0 p+4 p+8 p+16 p+24 Multiple of 4 Multiple of 8 Multiple of 8 • Unaligned Data • Aligned Data • Primitive data type requires K bytes • Address must be multiple of K
Alignment Principles • Aligned Data • Primitive data type requires K bytes • Address must be multiple of K • Motivation for Aligning Data • Memory accessed by (aligned) chunks of 4 or 8 bytes • Inefficient to load or store data that spans (quad) word boundaries • Virtual memory (later) • Compiler • Inserts gaps in structure to ensure correct alignment of fields • Assembler directive • .align 4 • aligns next data item to an address that is a multiple of 4
Specific Cases of Alignment (IA32) • 1 byte: char, … • no restrictions on address • 2 bytes: short, … • lowest 1 bit of address must be 02 • 4 bytes: int, float, char *, … • lowest 2 bits of address must be 002
Meeting Overall Alignment Requirement • For largest alignment requirement K • Overall structure must be multiple of K • needed for an array of structures struct S2 { double v; int i[2]; char c; } *p;
Saving Space • Put large data types first • Effect (K=4) structS5 { inti; char c; char d; } *p; structS4 { char c; inti; char d; } *p; (p+9) c 3 bytes i d 3 bytes i c d 2 bytes (p+6) printf (“%d”, sizeof (s)); // to see what the full padded size is
structrec { inta[3]; inti; structrec *n; }; Following Linked List - ON YOUR OWN • C Code void set_val (struct rec *r, int val) { while (r) { int i = r->i; r->a[i] = val; r = r->n; } } a i n 20 12 0 16 Element i .L17: # loop: movl 12(%edx), %eax # r->i movl %ecx, (%edx,%eax,4) # r->a[i] = val movl 16(%edx), %edx # r = r->n testl %edx, %edx # Test r jne .L17 # If != 0 goto loop
Summary • Arrays in C • Contiguous allocation of memory • Aligned to satisfy every element’s alignment requirement • Pointer to first element • No bounds checking • Structures • Allocate bytes in order declared, also contiguous • Pad in middle and at end to satisfy alignment • Parameters: pass address of array or structure
Next Time • Instruction set architecture: inside the CPU • Y86! • Chapter 4.1