J Mei J Mei - 1 year ago 77
C Question

Finding the dimensions of an array through assembly

I have an assignment to reverse engineer the assembly to find the values of R, S, and T in the following code. Assume that R, S, and T are constants declared with


long int A[R][S][T];
int store_ele(int h, int i, int j, long int *dest)
A[h][i][j] = *dest;
return sizeof(A);

When compiling this program, GCC generates the following assembly code (with -O2):

movslq %esi, %rsi //%rsi = h
movslq %edi, %rdi //%rdi = i
movq (%rcx), %rax //moves the value from %rcx to %rax
leaq (%rdi,%rdi,4), %rdi //%rdi = 4 * i + i
leaq (%rsi,%rsi,4), %rcx //%rcx = 4 * h + h
movslq %edx, %rdx //%rdx = j
leaq (%rcx,%rdi,4), %rcx //%rcx = 4 * %rdi + %rcx = 4 * (4 * i + i) + (4 * h + h)
addq %rcx, %rdx //adds something to j
movq %rax, A(,%rdx,8) //moves some value
movl $1120, %eax //%eax = 1120
ret //returns %eax

I want to ask if what I am understanding about the assembly is right and any tips or assistance is appreciated!

Edit: I don't know what it is called but our prof. defines
movq: source, destination
and other similar assembly instructions where the first argument is source and second is destination

Edit 2: Biggest issue is how do I find the values of the three constants just based on the assembly. I think

movq %rax, A(,%rdx,8) //moves some value
movl $1120, %eax //%eax = 1120
ret //returns %eax

Is going to play the main role in finding out what it does but I don't know what to do with it.

Answer Source

That's x86-64 AT&T syntax (mnemonic source, dest), with the x86-64 System V ABI (first arg in rdi, see this approximate summary of that calling convention, or find links to better ABI docs (including the official standards) in the tag wiki).

What you're calling "functions" are assembly instructions. Each one assembles to a single machine instruction.

Hint: your comments are wrong about which arg is which. Check the ABI for arg-passing order.

Since you know the declaration is long int A[R][S][T]:

A[h][i][j] is equivalent to *(A[h][i] + j), where A[h][i] is an array type (with size [T]). Applying this recursively, A[h][i][j] is equivalent to *(base_pointer + S*T*h + T*i + j) (where base_pointer is just a long*, for the purposes of C pointer math which implicitly scales by sizeof(long) in this case).

You seem to be on the right track working out how the LEAs are multiplying, so you can find T, then use that to find S (by dividing the factor for h).

Then to find R, look at the function return value, which is R*S*T * sizeof(long).

sizeof(long) in the x86-64 System V ABI is 8 bytes. The offset into the array is scaled by 8 bytes, too, of course, so don't forget to factor that out when getting your S and T values.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download