3.69
Solution
Let's annotate the assembly code
void test(long i, b_struct *bp)
i in %rdi, bp in %rsi
0000000000000000 <test>:
0: 8b 8e 20 01 00 00 mov 0x120(%rsi),%ecx # fetch bp->last
6: 030e add (%rsi),%ecx # bp->last + bp->first
8: 48 8d 04 bf lea (%rdi,%rdi,4),%rax # 5i
c: 48 8d 04 c6 lea (%rsi,%rax,8),%rax # %rax <- bp + 40i
10: 48 8b 50 08 mov 0x8(%rax),%rdx # %rdx <- M[bp + 40i + 8]
14: 48 63 c9 movslq %ecx,%rcx # sign-extend %ecx
17: 48 89 4c d0 10 mov %rcx,0x10(%rax,%rdx,8) # M[bp + 40i + 16 + %rdx*8] <- %rcx
1c: c3 retq
bp->lasthas an offset of 288 \(\implies\)sizeof(int) + padding + sizeof(a_struct) * CNTis 288.ap=bp + 8 + 40i%rdxstoresap->idx
A.
In b_struct, first comes before the array a[CNT], and as we can see from the way ap is gotten,
there is an extra offset of 8 apart from the offset caused by preceding elements in a.
These 8 bits include int first, and a padding of 4 bytes after that.
From the first point, we see 4 + 4 + 40 * CNT = 288 \(\implies\) CNT = 7.
B.
In the final mov instruction, bp + 40i + 16 + %rdx * 8 can be written as
ap + 8 + idx * 8.
We can conclude from this that in a_struct, the first 8 bits are occupied by idx, and the later
bits are occupied by an array with elements of size 8, i.e. of type long.
Because the size of a_struct is 40 (from its array in b_struct), \(8 + 8 * len(x) = 40\).
We obtain that length of array x is 4.
typedef struct {
long idx;
long x[4];
};