Today Arrays One-dimensional Machine-Level Programming IV: Data Multi-dimensional (nested) Multi-level Structures CSci 2021: Machine Architecture and Organization Allocation March 2nd-4th, 2020 Access Your instructor: Stephen McCamant Alignment Based on slides originally by: Randy Bryant, Dave O’Hallaron 1 2 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Array Allocation Array Access Basic Principle Basic Principle T A[ L ]; T A[ L ]; Array of data type T and length L Array of data type T and length L Contiguously allocated region of L * sizeof ( T ) bytes in memory Identifier A can be used as a pointer to array element 0: Type T* char string[12]; int val[5]; 1 5 2 1 3 x x + 12 x x + 4 x + 8 x + 12 x + 16 x + 20 int val[5]; Reference Type Value x x + 4 x + 8 x + 12 x + 16 x + 20 val[4] int 3 double a[3]; val int * x val+1 int * x + 4 x x + 8 x + 16 x + 24 &val[2] int * x + 8 char *p[3]; val[5] int ?? *(val+1) int 5 x x + 8 x + 16 x + 24 val + i int * x + 4 i 3 4 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Array Example Array Accessing Example #define ZLEN 5 typedef int zip_dig[ZLEN]; zip_dig cmu; 1 5 2 1 3 zip_dig cmu = { 1, 5, 2, 1, 3 }; 16 20 24 28 32 36 zip_dig mit = { 0, 2, 1, 3, 9 }; zip_dig ucb = { 9, 4, 7, 2, 0 }; int get_digit zip_dig cmu; 1 5 2 1 3 (zip_dig z, int digit) { 16 20 24 28 32 36 return z[digit]; zip_dig mit; 0 2 1 3 9 Register %rdi contains } starting address of array 36 40 44 48 52 56 x86: Register %rsi contains zip_dig ucb; 9 4 7 2 0 array index # %rdi = z 56 60 64 68 72 76 # %rsi = digit Desired digit at movl (%rdi,%rsi,4), %eax # z[digit] %rdi + 4*%rsi Declaration “ zip_dig cmu ” equivalent to “ int cmu[5] ” Use memory reference Example arrays were allocated in successive 20 byte blocks (%rdi,%rsi,4) Not guaranteed to happen in general 5 6 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Array Loop Example Multidimensional (Nested) Arrays Declaration void zincr(zip_dig z) { A[0][0] • • • A[0][C-1] T A [ R ][ C ]; size_t i; • • for (i = 0; i < ZLEN; i++) 2D array of data type T • • z[i]++; R rows, C columns • • } Type T element requires K bytes A[R-1][0] • • • A[R-1][C-1] Array Size R * C * K bytes # %rdi = z movl $0, %eax # i = 0 Arrangement jmp .L3 # goto middle Row-Major Ordering .L4: # loop: addl $1, (%rdi,%rax,4) # z[i]++ addq $1, %rax # i++ int A[R][C]; .L3: # middle A A A A A A cmpq $4, %rax # i:4 [0] • • • [0] [1] • • • [1] • • • [R-1] • • • [R-1] jbe .L4 # if <=, goto loop [0] [C-1] [0] [C-1] [0] [C-1] rep; ret 4*R*C Bytes 7 10 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Nested Array Example Nested Array Row Access #define PCOUNT 4 Row Vectors zip_dig pgh[PCOUNT] = A[i] is array of C elements {{1, 5, 2, 0, 6}, Each element of type T requires K bytes {1, 5, 2, 1, 3 }, {1, 5, 2, 1, 7 }, Starting address A + i * ( C * K ) {1, 5, 2, 2, 1 }}; int A[R][C]; zip_dig 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 pgh[4]; A[0] A[i] A[R-1] 76 96 116 136 156 A A A A A A [0] [0] • • • [i] [i] • • • [R-1] [R-1] • • • • • • • • • “ zip_dig pgh[4] ” equivalent to “ int pgh[4][5] ” [0] [C-1] [0] [C-1] [0] [C-1] Variable pgh : array of 4 elements, allocated contiguously Each element is an array of 5 int ’s , allocated contiguously A A+(i*C*4) A+((R-1)*C*4) “Row - Major” ordering of all elements in memory 11 12 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Nested Array Row Access Code Nested Array Element Access 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 Array Elements A[i][j] is element of type T, which requires K bytes int *get_pgh_zip(int index) pgh Address A + i * ( C * K ) + j * K = A + ( i * C + j ) * K { return pgh[index]; } # %rdi = index int A[R][C]; leaq (%rdi,%rdi,4),%rax # 5 * index leaq pgh(,%rax,4),%rax # pgh + (20 * index) A[0] A[i] A[R-1] Row Vector A A A A A pgh[index] is array of 5 int ’s [0] [0] • • • [i] • • • [R-1] [R-1] • • • • • • • • • • • • Starting address pgh+20*index [0] [C-1] [j] [0] [C-1] Machine Code A A+(i*C*4) A+((R-1)*C*4) Computes and returns address Compute as pgh + 4*(index+4*index) A+(i*C*4)+(j*4) 13 14 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Nested Array Element Access Code Multi-Level Array Example Variable univ denotes 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 zip_dig umn = { 5, 5, 4, 5, 5 }; array of 3 elements zip_dig mit = { 0, 2, 1, 3, 9 }; zip_dig ucb = { 9, 4, 7, 2, 0 }; Each element is a pointer pgh int get_pgh_digit 8 bytes (int index, int dig) #define UCOUNT 3 { int *univ[UCOUNT] = {mit, umn, ucb}; Each pointer points to array return pgh[index][dig]; of int ’s } leaq (%rdi,%rdi,4), %rax # 5*index umn addl %rax, %rsi # 5*index+dig 5 5 4 5 5 univ movl pgh(,%rsi,4), %eax # M[pgh + 4*(5*index+dig)] 16 20 24 28 32 36 36 mit 160 Array Elements 0 2 1 3 9 168 16 pgh[index][dig] is int 36 40 44 48 52 56 ucb 176 56 Address: pgh + 20*index + 4*dig 9 4 7 2 0 = pgh + 4*(5*index + dig) 56 60 64 68 72 76 15 16 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Element Access in Multi-Level Array Array Element Accesses int get_univ_digit umn Multi-level array 5 5 4 5 5 Nested array (size_t index, size_t digit) univ 36 16 20 24 28 32 36 160 mit int get_pgh_digit int get_univ_digit { 0 2 1 3 9 16 168 return univ[index][digit]; 56 ucb 36 40 44 48 52 56 (size_t index, size_t digit) (size_t index, size_t digit) 176 9 4 7 2 0 { { } 56 60 64 68 72 76 return pgh[index][digit]; return univ[index][digit]; } } salq $2, %rsi # 4*digit addq univ(,%rdi,8), %rsi # p = univ[index] + 4*digit umn movl (%rsi), %eax # return *p 5 5 4 5 5 univ 16 ret 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 36 20 24 28 32 36 160 mit 0 2 1 3 9 16 168 36 56 ucb 40 44 48 52 56 176 76 96 116 136 156 9 4 7 2 0 56 60 64 68 72 76 Computation Element access Mem[Mem[univ+8*index]+4*digit] Accesses looks similar in C, but address computations very different: Must do two memory reads Mem[pgh+20*index+4*digit] Mem[Mem[univ+8*index]+4*digit] First get pointer to row array Then access element within array 17 18 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition N X N Matrix #define N 16 16 X 16 Matrix Access typedef int fix_matrix[N][N]; Code /* Get element a[i][j] */ int fix_ele(fix_matrix a, Array Elements Fixed dimensions size_t i, size_t j) Address A + i * ( C * K ) + j * K Know value of N at { C = 16, K = 4 return a[i][j]; compile time } #define IDX(n, i, j) ((i)*(n)+(j)) /* Get element a[i][j] */ Variable dimensions, /* Get element a[i][j] */ int fix_ele(fix_matrix a, size_t i, size_t j) { explicit indexing int vec_ele(size_t n, int *a, return a[i][j]; size_t i, size_t j) Traditional way to } { implement dynamic return a[IDX(n,i,j)]; # a in %rdi, i in %rsi, j in %rdx arrays } salq $6, %rsi # 64*i addq %rsi, %rdi # a + 64*i /* Get element a[i][j] */ movl (%rdi,%rdx,4), %eax # M[a + 64*i + 4*j] Variable dimensions, int var_ele(size_t n, int a[n][n], ret implicit indexing size_t i, size_t j) { return a[i][j]; Now supported by gcc } 19 20 Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Recommend
More recommend