通过一次查看一行代码,最容易解释发生了什么。
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
这是使用A
偏移量 eax*4 访问数组并将其存储在 edx 中。
由于 eax 是i*63 + j*9 + k
,您可以将其视为在 offset 处访问单个维度 int 数组i*63 + j*9 + k
。我们乘以 4,因为那是 int 的大小。
请注意,您可以将该索引表达式重写为i*7*9 + j*9 + k
. 从那开始,我希望你可以开始了解数组的各个维度是如何被访问的。
10. movl 20(%ebp), %eax
这将使用 ebp+20 处的参数加载 eax,即dest
.
11. movl %edx, (%eax)
这会将我们刚刚从数组中得到的 edx 存储在 eax ( dest
) 中的地址处。*dest = A[i*7*9 + j*9 + k]
如果A
是一维 int 数组,它会有效地做;
12. movl $2772, %eax
这只是返回值 2772,大小为A
.
既然您现在知道 的大小A
,如果您回顾一下在取消引用数组时是如何乘以和乘以的i
,我希望您可以很容易地计算出,和的值。j
k
R
S
T
更新:计算尺寸
如果您的数组的维度是R
,S
和T
,那么要访问 , , 处的元素,i
您将使用什么公式?j
k
将数组视为具有维度的大型三维块R x S x T
。索引从该i
块中选择一个二维切片,其维度为S x T
。索引从该j
长度切片中选择一行T
。并且k
索引只是该k
行中的第一项。
所以一维地址可以表示为i*S*T + j*T + k
。现在,如果您回顾上面反汇编中的数组计算,您是否没有注意到相同的模式?你能看到反汇编映射到S
和的哪些值T
吗?
至于查找R
:你知道数组中的项目数是693(2772字节大小除以4的int大小);而且您还知道可以使用R*S*T
(再次考虑三维块)来计算项目的数量。因此R*S*T = 693
和 你知道S
和T
,所以找到R
只是一个除法的问题。