Skip to content

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->last has an offset of 288 \(\implies\) sizeof(int) + padding + sizeof(a_struct) * CNT is 288.
  • ap = bp + 8 + 40i
  • %rdx stores ap->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];
};