汇编代码使用数组

时间:2013-05-12 15:53:08

标签: assembly systems-programming

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生成以下汇编代码:

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

问题:http://i.imgur.com/szB1XnE.jpg

我不理解上面汇编代码中的第9行和这些问题。

1 个答案:

答案 0 :(得分:1)

最容易通过一次查看代码来解释发生了什么。

1.  movl 8(%ebp), %ecx

这将使用ebp + 8中的参数加载ecx,即i

2.  movl 12(%ebp), %eax

这将使用参数ebp + 12加载eax,即j

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

这将eax设置为eax + eax * 8,基本上将其自身乘以9.所以eax现在是j*9

4.  movl %ecx, %edx

这将edx设置为ecx,即i

5.  sall $6, %edx

这会将它左移6位,乘以64,所以edx现在为i*64

6.  sub1 %ecx, %edx

但现在我们从该值中减去ecx(i),因此edx变为i*63

7.  addl %edx, %eax

这将edx(i*63)添加到eax(j*9),因此eax现在为i*63 + j*9

8.  addl 16(%ebp), %eax

这会在ebp + 16处添加k的参数,因此eax现在为i*63 + j*9 + k

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

这是使用偏移量eax * 4访问A数组并将其存储在edx中。

由于eax为i*63 + j*9 + k,您可以将其视为访问偏移i*63 + j*9 + k处的单个维度int数组。我们乘以4,因为这是int的大小。

请注意,您可以将该索引表达式重写为i*7*9 + j*9 + k。从那以后,我希望你能开始看到如何访问数组的各个维度。

10. movl 20(%ebp), %eax

此加载eax的参数为ebp + 20,即dest

11. movl %edx, (%eax)

这将存储edx,我们刚从数组中获取的内容,位于eax(dest)中的地址。如果*dest = A[i*7*9 + j*9 + k]是单维int数组,它实际上正在A;

12. movl $2772, %eax

这只是返回值2772,即A的大小。

由于你现在知道A的大小,如果你回顾一下ijk在解除引用数组时的倍数,我就是希望你能够很容易地找出RST的值。

更新:计算尺寸

如果您的数组的维度为RST,那么要访问ij,{{1}的元素你将使用什么公式?

将数组视为维度为k的大三维块。 R x S x T索引从该块中选择维度为i的二维切片。 S x T索引从长度为j的切片中选择一行。 T索引只是该行中的k项。

因此,一维地址可以表示为k。现在,如果您回顾上面反汇编中的数组计算,您是否注意到相同的模式?您能看到反汇编映射中的哪些值为i*S*T + j*T + kS吗?

至于查找T:你知道数组中的项数是693(2772字节大小除以int大小4);并且您还知道可以使用R计算项目数(再次考虑三维块)。因此R*S*T并且您知道R*S*T = 693S,因此查找T只是一个划分问题。

相关问题