For data type T and integer constant n, consider the declaration
T arr[n];
Let L be the size (in bytes) of the data type T. The declaration allocates a contiguous region of L * n bytes. It also introduces an identifier arr that at can be used as a pointer to the beginning of the array. Let the value of that pointer be denoted Xarr. The elements can be accessed using integer indices 0 – (n-1). Thus array element i will be stored at Xarr + (L * i).
Examples
Element Size (bytes) | Total Size | Start Address | Element i | |
char A[12]; | 1 | 12 | XA | XA + (1 * i) |
char* B[8]; | 8 | 64 | XB | XB + (8 * i) |
int C[6]; | 4 | 24 | XC | XC + (4 * i) |
double* D[5]; | 8 | 40 | XD | XD + (8 * i) |
Accessing Array Element i in Assembly
Suppose E is an array of values of type int. Suppose the address of XE is stored in %rdx and some integer i is stored in %rcx. Then to get the value of E[i] and store it in %eax we do the following:
movl (%rdx, %rcx, 4), %eax
Pointer Arithmetic
Pointer arithmetic allows us to traverse an array. If p is a pointer to data of type T that has size L, and the value of p is Xp, then
p + 1 has the value Xp + (L * 1) p + 2 has the value Xp + (L * 2)
and
*(p + i) is the value at Xp + (L * i)
Example
Suppose E is an array of values of type int. Suppose the address of XE is stored in %rdx and some integer i is stored in %rcx.
Expression | Type | Value | Assembly Code |
E | int* | XE | movq %rdx, %rax |
E[0] | int | M[XE] | movl (%rdx), %eax |
E[i] | int | M[XE+4i] | movl (%rdx, %rcx, 4), %eax |
&E[2] | int* | XE + 8 | leaq 8(%rdx), %rax |
E+i-1 | int* | XE + 4i – 4 | leaq -4(%rdx, %rcx, 4), %rax |
*(E+i-3) | int | M[XE +4i – 12] | movl -12(%rdx, %rcx, 4), %eax |
© 2017 – 2018, Eric. All rights reserved.