double A[50]; int B[10][50]; char C[10][20][5];
A - 50 elements * 8 bytes = 400 bytes
B - 10 elements * 50 elements * 4 bytes = 2000 bytes
C - 10 elements * 20 elements * 5 elements * 1 bytes = 1000 bytes
A starts at 100
B starts at 500
C starts at 2500
| Register | holds: |
| %edx | &B |
| %ecx | i |
| %ebx | j |
leal (,%ebx,4),%ebx -- ebx has j*4 imull $200,%ecx -- i*200 addl %ecx,%ebx -- i*200+j*4 movl (%edx,%ebx),eax
typedef struct { typedef union {
char c; char c;
double *p; double *p;
int i; int i;
double d; double d;
short s; short s;
} struct1; } union1;
|
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
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|c |xxxxxxxx| p | i |xxxxxxxxxxx| d | s | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
If we place d first followed by p, i, s and c, this will take 19 bytes
8, the size of the largest field (which is double).
struct s1 { struct s2 { union u1 {
char a[3]; 0 struct s1 *d; 0 struct s1 *h; 0
union u1 b; 4 char e; 4 struct s2 *i; 4
int c; 8 int f[4]; 8 char j; 8
}; struct s2 *g; 24 };
};
You may find it helpful to diagram these data structures before considering the code below.
Offsets added aboveFor each IA32 assembly code sequence below on the left, fill in the missing portion of corresponding C code on the right.
proc1: int proc1(struct s2 *x) {
pushl %ebp
movl %esp,%ebp return x->f[1]; }
movl 8(%ebp),%eax -- get x (struct ptr)
movl 12(%eax),%eax -- add offset 12 to address of x, this indexes to the second array element
movl %ebp,%esp
popl %ebp
ret
proc2: int proc2(struct s1 *x) {
pushl %ebp
movl %esp,%ebp return x->b.i ->f[3] }
movl 8(%ebp),%eax -- get x (struct ptr)
movl 4(%eax),%eax -- load union value (offset 4)
movl 20(%eax),%eax -- assuming pointer to struct2 (offset too big for struct1), use offset 20 to get to last element in f
movl %ebp,%esp
popl %ebp
ret
proc3: char proc3(union u1 *x) {
pushl %ebp
movl %esp,%ebp return x->i->e }
movl 8(%ebp),%eax -- get x (union ptr)
movl (%eax),%eax -- treat x as pointer - load element
movsbl 4(%eax),%eax -- load a character - struct s2 has character at offset 4
movl %ebp,%esp
popl %ebp
ret
proc4: char proc4(union u1 *x) {
pushl %ebp
movl %esp,%ebp return x->g->d->a[1]; }
movl 8(%ebp),%eax -- get x (union ptr)
movl (%eax),%eax -- treat x as pointer - load element
movl 24(%eax),%eax -- load from s2 at offset 24
movl (%eax),%eax -- this is a pointer to s2 - load element
movsbl 1(%eax),%eax -- load a character - struct s1 has character at offset 1
movl %ebp,%esp
popl %ebp
ret