Presentation is loading. Please wait.

Presentation is loading. Please wait.

Machine-Level Programming 5 Structured Data

Similar presentations


Presentation on theme: "Machine-Level Programming 5 Structured Data"— Presentation transcript:

1 Machine-Level Programming 5 Structured Data
Topics Arrays

2 Basic Data Types Integral Floating Point
Stored & operated on in general registers Signed vs. unsigned depends on instructions used Intel GAS Bytes C byte b 1 [unsigned] char word w 2 [unsigned] short double word l 4 [unsigned] int Floating Point Stored & operated on in floating point registers Single s 4 float Double l 8 double Extended t 10/12/16 long double

3 Array Allocation Basic Principle T A[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[4]; x + 32 x + 24 x x + 8 x + 16 char *p[3]; x x + 4 x + 8 x + 12

4 Array Access Basic Principle Reference Type Value T A[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] val val+1 &val[2] val[5] *(val+1) val + i 1 5 2 3 int val[5]; x x + 4 x + 8 x + 12 x + 16 x + 20 int 3 int * x int * x + 4 int * x + 8 int ???? int 5 int * x + 4i

5 Array Example Notes typedef int zip_dig[5];
zip_dig cmu = { 1, 5, 2, 1, 3 }; zip_dig mit = { 0, 2, 1, 3, 9 }; zip_dig umbc = { 2, 1, 2, 5, 0 }; zip_dig cmu; 1 5 2 3 16 20 24 28 32 36 zip_dig mit; 9 40 44 48 52 56 zip_dig umbc; 60 64 68 72 76 Notes Declaration “zip_dig umbc” equivalent to “int umbc[5]” Example arrays were allocated in successive 20 byte blocks Not guaranteed to happen in general

6 Array Accessing Example
Computation Register %edx contains starting address of array Register %eax contains array index Desired digit at 4*%eax + %edx Use memory reference (%edx,%eax,4) int get_digit (zip_dig z, int dig) { return z[dig]; } IA32 Memory Reference Code # %edx = z # %eax = dig movl (%edx,%eax,4),%eax # z[dig]

7 Referencing Examples Code Does Not Do Any Bounds Checking!
zip_dig cmu; 1 5 2 3 16 20 24 28 32 36 zip_dig mit; 9 40 44 48 52 56 zip_dig umbc; 60 64 68 72 76 Code Does Not Do Any Bounds Checking! Reference Address Value Guaranteed? mit[3] mit[5] mit[-1] cmu[15] Yes 36 + 4*3 = 48 3 No 36 + 4*5 = 56 2 No 36 + 4*(-1) = 32 3 No 16 + 4*15 = 76 ?? Out of range behavior implementation-dependent No guaranteed relative allocation of different arrays

8 Array Loop Example Original Source Transformed Version
int zd2int(zip_dig z) { int i; int zi = 0; for (i = 0; i < 5; i++) { zi = 10 * zi + z[i]; } return zi; Original Source Transformed Version As generated by GCC Eliminate loop variable i Convert array code to pointer code Express in do-while form No need to test at entrance int zd2int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while (z <= zend); return zi; }

9 Array Loop Implementation (IA32)
Registers %ecx z %eax zi %ebx zend Computations 10*zi + *z implemented as *z + 2*(zi+4*zi) z++ increments by 4 int zd2int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while(z <= zend); return zi; } int zd2int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while(z <= zend); return zi; } int zd2int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while(z <= zend); return zi; } int zd2int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while(z <= zend); return zi; } int zd2int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while(z <= zend); return zi; } # %ecx = z xorl %eax,%eax # zi = 0 leal 16(%ecx),%ebx # zend = z+4 .L59: movl (%ecx),%eax # *z leal (%eax,%eax,4),%edx # 5*zi leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi) addl $4,%ecx # z++ cmpl %ebx,%ecx # z : zend jle .L59 # if <= goto loop # %ecx = z xorl %eax,%eax # zi = 0 leal 16(%ecx),%ebx # zend = z+4 .L59: leal (%eax,%eax,4),%edx # 5*zi movl (%ecx),%eax # *z addl $4,%ecx # z++ leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi) cmpl %ebx,%ecx # z : zend jle .L59 # if <= goto loop # %ecx = z xorl %eax,%eax # zi = 0 leal 16(%ecx),%ebx # zend = z+4 .L59: leal (%eax,%eax,4),%edx # 5*zi movl (%ecx),%eax # *z addl $4,%ecx # z++ leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi) cmpl %ebx,%ecx # z : zend jle .L59 # if <= goto loop # %ecx = z xorl %eax,%eax # zi = 0 leal 16(%ecx),%ebx # zend = z+4 .L59: leal (%eax,%eax,4),%edx # 5*zi movl (%ecx),%eax # *z addl $4,%ecx # z++ leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi) cmpl %ebx,%ecx # z : zend jle .L59 # if <= goto loop # %ecx = z xorl %eax,%eax # zi = 0 leal 16(%ecx),%ebx # zend = z+4 .L59: leal (%eax,%eax,4),%edx # 5*zi movl (%ecx),%eax # *z addl $4,%ecx # z++ leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi) cmpl %ebx,%ecx # z : zend jle .L59 # if <= goto loop

10 Array Code Example int main ( ) { int i, sum, array[4];
for (i = 0; i < 4; i++ ) array[i] = i << 2; sum = sumArray( array ); printf( "Array sum = %d\n", sum); return 0; } int sumArray( int a[ ] ) return a[1] + a[3];

11 sumArray 08048390 <sumArray>: 8048390: 55 push %ebp # setup
int sumArray( int a[ ] ) { return a[ 1 ] + a[ 3 ]; } <sumArray>: : push %ebp # setup : e mov %esp,%ebp # setup : b mov 0x8(%ebp),%edx # edx = a : d pop %ebp # finish up : b 42 0c mov 0xc(%edx),%eax # a[ 3 ] 804839a: b 4a mov 0x4(%edx),%ecx # a[ 1 ] 804839d: c add %ecx,%eax # return sum 804839f: c ret

12 main int main ( ) { int i, sum, aa[4]; for (i = 0; i < 4; i++ )
aa[i] = i << 2; // aa[i] = i * 4 sum = sumArray( aa ); printf( "Array sum = %d\n", sum); return 0; }

13 main 080483a0 <main>: 80483a0: 31 d2 xor %edx,%edx # i = 0
# missing setup code 80483b0: 83 ec sub $0x24,%esp # big stack 80483b3: 8d 4d ec lea 0xffffffec(%ebp),%ecx # aa at ebp - 0x14 80483b6: 8d lea 0x0(%esi),%esi # filler 80483b9: 8d bc lea 0x0(%edi),%edi # filler L1: # word boundary 80483c0: 8d lea 0x0(,%edx,4),%eax # i * 4 80483c7: mov %eax,(%ecx,%edx,4) # a[ i ] 80483ca: inc %edx # i++ 80483cb: 83 fa cmp $0x4,%edx # compare i : 4 80483ce: 75 f jne c0 <main+0x20> # loop L1 ?? 80483d0: 89 0c mov %ecx,(%esp) # “push” param 80483d3: e8 b8 ff ff ff call <sumArray> # 80483d8: c d movl $0x80484d8,(%esp) # for printf 80483df: mov %eax,0x4(%esp) # for printf 80483e3: e8 d4 fe ff ff call bc # 80483e8: 83 c add $0x24,%esp # resest esp 80483eb: 31 c xor %eax,%eax # return 0 # missing finish code 80483ed: C3 ret

14 Nested Array Example #define PCOUNT 4 zip_dig md[PCOUNT] = {{2, 1, 1, 6, 2}, {2, 1, 2, 2, 8 }, {2, 1, 0, 4, 2 }, {2, 1, 2, 1, 0 }}; zip_dig md[4]; 76 96 116 136 156 2 1 6 8 4 Declaration “zip_dig md[4]” equivalent to “int md[4][5]” Variable md denotes array of 4 elements Allocated contiguously Each element is an array of 5 int’s “Row-Major” ordering of all elements guaranteed

15 Viewing as Multidimensional Array
Declaration T A[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 A[0][0] A[0][C-1] A[R-1][0] • • • A[R-1][C-1] int A[R][C]; A [0] [C-1] • • • [1] [R-1] •  •  • 4*R*C Bytes

16 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 [0] [C-1] • • • A[0] A [i] [0] [C-1] • • • A[i] A [R-1] [0] [C-1] • • • A[R-1] •  •  • •  •  • A A+i*C*4 A+(R-1)*C*4

17 Nested Array Row Access Code
int *get_md_zip(int index) { return md[index]; } Row Vector md is a 2-d array of ints, 5 ints per row md[index] is array of 5 ints Starting address of md[index] is md + 20*index IA32 Code Computes and returns address Compute as md + 4*(index + 4*index) # %eax = index leal (%eax,%eax,4),%eax # 5 * index leal md(,%eax,4),%eax # md + (20 * index)

18 Nested Array Element Access
Array Elements A[i][j] is element of type T Address A + i * (C * K) + j * K = A + (i * C + j)* K A [i] [j] int A[R][C]; A [0] [C-1] • • • A[0] A[i] A [R-1] [0] [C-1] • • • A[R-1] •  •  • • • • • • • A [i] [j] •  •  • A A+i*C*4 A+(R-1)*C*4 A+(i*C+j)*4

19 Nested Array Element Access Code
Array Elements md[index][dig] is int Address: md + 20*index + 4*dig IA32 Code Computes address md + 4*dig + 4*(index+4*index) movl performs memory reference int get_md_digit (int index, int dig) { return md[index][dig]; } # %ecx = dig # %eax = index leal 0(,%ecx,4),%edx # 4*dig leal (%eax,%eax,4),%eax # 5*index movl md(%edx,%eax,4),%eax # *(md + 4*dig + 20*index)

20 Strange Referencing Examples
zip_dig md[4]; 76 96 116 136 156 2 1 6 8 4 Reference Address Value Guaranteed? md[3][3] 76+20*3+4*3 = 148 1 md[2][5] 76+20*2+4*5 = 136 2 md[2][-1] 76+20*2+4*-1 = 112 8 md[4][-1] 76+20*4+4*-1 = 152 0 md[0][19] 76+20*0+4*19 = 152 0 md[0][-1] 76+20*0+4*-1 = 72 ?? Code does not do any bounds checking Ordering of elements within array guaranteed Yes Yes Yes Yes Yes No

21 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 umbc = { 2, 1, 2, 5, 0 }; #define UCOUNT 3 int *univ[UCOUNT] = {mit, cmu, umbc}; 36 160 16 56 164 168 univ cmu 1 5 2 3 20 24 28 32 mit 9 40 44 48 52 umbc 4 7 60 64 68 72 76

22 Element Access in Multi-Level Array
int get_univ_digit (int index, int dig) { return univ[index][dig]; } Computation (IA32) Element access Mem[Mem[univ + 4*index] + 4*dig] Must do two memory reads First get pointer to row array Then access element within array # %ecx = index # %eax = dig leal 0(,%ecx,4),%edx # 4*index movl univ(%edx),%edx # Mem[univ + 4*index] movl (%edx,%eax,4),%eax # Mem[ *dig]

23 Array Element Accesses
Similar C references Nested Array Element at Mem[md+20*index+4*dig] Different address computation Multi-Level Array Element at Mem[Mem[univ+4*index]+4*dig] int get_md_digit (int index, int dig) { return md[index][dig]; } int get_univ_digit (int index, int dig) { return univ[index][dig]; } cmu cmu 9 4 7 2 29 1 5 56 60 64 68 72 76 1 5 2 3 16 20 24 28 32 36 1 5 2 3 1 1 5 5 2 2 1 1 3 3 36 160 16 56 164 168 univ univ univ 76 96 116 136 156 1 5 2 6 3 7 160 160 16 16 20 20 24 24 28 28 32 32 36 36 36 36 mit mit 2 1 3 9 36 40 44 48 52 56 2 1 3 9 2 2 1 1 3 3 9 9 164 164 16 16 umbc ucb 36 36 40 40 44 44 48 48 52 52 56 56 168 168 56 56 9 4 7 2 56 60 64 68 72 76 9 4 7 2 56 60 64 68 72 76

24 Strange Referencing Examples
36 160 16 56 164 168 univ cmu 1 5 2 3 20 24 28 32 mit 9 40 44 48 52 umbc 4 7 60 64 68 72 76 Reference Address Value Guaranteed? univ[2][3] 56+4*3 = 68 2 univ[1][5] 16+4*5 = 36 0 univ[2][-1] 56+4*-1 = 52 9 univ[3][-1] ?? ?? univ[1][12] 16+4*12 = 64 7 Code does not do any bounds checking Ordering of elements in different arrays not guaranteed Yes No No No No

25 Using Nested Arrays Strengths Limitation
#define N 16 typedef int fix_matrix[N][N]; Strengths C compiler handles doubly subscripted arrays Generates very efficient code Avoids multiply in index computation Limitation Only works if have fixed array size /* Compute element i,k of fixed matrix product */ int fix_prod_ele (fix_matrix a, fix_matrix b, int i, int k) { int j; int result = 0; for (j = 0; j < N; j++) result += a[i][j]*b[j][k]; return result; } A (i,*) B (*,k) Column-wise Row-wise

26 Dynamic Nested Arrays Strength Programming Performance
Can create matrix of arbitrary size Programming Must do index computation explicitly Performance Accessing single element costly Must do multiplication int * new_var_matrix(int n) { return (int *) calloc(sizeof(int), n*n); } int var_ele (int *a, int i,int j, int n) { return a[i*n + j]; } movl 12(%ebp),%eax # i movl 8(%ebp),%edx # a imull 20(%ebp),%eax # n*i addl 16(%ebp),%eax # n*i+j movl (%edx,%eax,4),%eax # Mem[a+4*(i*n+j)]

27 Dynamic Array Multiplication
Without Optimizations Multiplies 2 for subscripts 1 for data Adds 2 for array indexing 1 for loop index /* Compute element i,k of variable matrix product */ int var_prod_ele (int *a, int *b, int i, int k, int n) { int j; int result = 0; for (j = 0; j < n; j++) result += a[i*n+j] * b[j*n+k]; return result; } A (i,*) B (*,k) Column-wise Row-wise

28 Optimizing Dynamic Array Mult.
{ int j; int result = 0; for (j = 0; j < n; j++) result += a[i*n+j] * b[j*n+k]; return result; } Optimizations Performed when set optimization level to -O2 Code Motion Expression i*n can be computed outside loop Strength Reduction Incrementing j has effect of incrementing j*n+k by n Performance Compiler can optimize regular access patterns { int j; int result = 0; int iTn = i*n; int jTnPk = k; for (j = 0; j < n; j++) { result += a[iTn+j] * b[jTnPk]; jTnPk += n; } return result;

29 Summary Arrays in C 2-D Arrays in C Contiguous allocation of memory
Pointer to first element No bounds checking 2-D Arrays in C “nested” -- int grades[ 4 ][ 6 ]; Nr rows, columns fixed Dynamic -- int *grades[ 6 ]; Nr rows dynamic, nr columns fixed Double subscripts work in both cases Compiler generates different code


Download ppt "Machine-Level Programming 5 Structured Data"

Similar presentations


Ads by Google