anna
anna

Reputation: 77

An assembly code used array

int A[R][S][T];

int A[R][S][T];
int store_ele(int i, int j, int k, int *dest) {
    *dest = A[i][j][k];
    return sizeof(A);
}

Gcc generates the following assembly code :

1.  movl 8(%ebp), %ecx
2.  movl 12(%ebp), %eax
3.  leal (%eax, %eax, 8), %eax
4.  movl %ecx, %edx
5.  sall $6, %edx
6.  sub1 %ecx, %edx
7.  addl %edx, %eax
8.  addl 16(%ebp), %eax
9.  movl A(,%eax,4), %edx
10. movl 20(%ebp), %eax
11. movl %edx, (%eax)
12. movl $2772, %eax

Questions : https://i.sstatic.net/Ba1Z2.jpg

I don't understand line 9 in assembly code above and these questions.

Upvotes: 0

Views: 1379

Answers (1)

James Holderness
James Holderness

Reputation: 23001

It's easiest to explain what is going on, by looking at the code one line at a time.

1.  movl 8(%ebp), %ecx

This loads ecx with the parameter at ebp+8, which is i.

2.  movl 12(%ebp), %eax

This loads eax with the parameter at ebp+12, which is j.

3.  leal (%eax, %eax, 8), %eax

This sets eax to eax+eax*8, basically multiplying itself by 9. So eax is now j*9.

4.  movl %ecx, %edx

This sets edx to ecx which is i.

5.  sall $6, %edx

And this shifts it left 6 bits, multiplying it by 64, so edx is now i*64.

6.  sub1 %ecx, %edx

But now we subtract ecx (which is i) from that value, so edx becomes i*63.

7.  addl %edx, %eax

This add edx (i*63) to eax (j*9), so eax is now i*63 + j*9.

8.  addl 16(%ebp), %eax

And this add the parameter at ebp+16 which is k, so eax is now i*63 + j*9 + k.

9.  movl A(,%eax,4), %edx

This is accessing the A array with the offset eax*4 and storing it in edx.

Since eax is i*63 + j*9 + k, you can think of this as accessing a single dimenson int array at offset i*63 + j*9 + k. We multiply by 4 because that's the size of an int.

Note that you can rewrite that index expression as i*7*9 + j*9 + k. From that, I hope you can start to see how the various dimensions of the array are being accessed.

10. movl 20(%ebp), %eax

This load eax with the parameter at ebp+20, which is dest.

11. movl %edx, (%eax)

And this stores edx, what we just got from our array, at the address in eax (dest). It's effectively doing *dest = A[i*7*9 + j*9 + k] if A were a single dimension int array;

12. movl $2772, %eax

This is just returning the value 2772, the size of A.

Since you now know the size of A, if you look back at how i, j and k have been multiplied when dereferencing the array, I'm hoping it should be fairly easy for you to figure out the values for R, S and T.

UPDATE: calculating the dimensions

If the dimensions of your array are R, S and T, then to access an element at i,j,k, what is the formula you would use?

Think of the array as a big three dimensional block with dimensions R x S x T. The i index selects a two dimensional slice from that block with dimensions S x T. The j index selects a row from that slice of length T. And the k index is just the kth item in that row.

So the one dimensional address can be represented as i*S*T + j*T + k. Now if you look back at the array calculations in the disassembly above, do you not notice that same pattern? Can you see which values in the disassembly map to S and T?

As for finding R: you know that the number of items in the array is 693 (the 2772 byte size divided by the int size of 4); and you also know that the number of items can be calculated with R*S*T (think of the three dimensional block again). Therefore R*S*T = 693 and you know S and T, so finding R is just a matter of division.

Upvotes: 1

Related Questions