所以我想用下面的代码与给出的汇编代码计算M和N的值。
int array1[M][N];
int array2[N][M];
void copyelement(int i, int j) {
array1[i][j] = array2[j][i];
}
汇编。
copyelement:
movslq %esi, %rsi
movslq %edi, %rdi
leaq (%rdi,%rdi,8), %rax
addq %rsi, %rax
leaq (%rsi,%rsi,2), %rdx
leaq (%rsi,%rdx,4), %rdx
addq %rdx, %rdi
leaq array2(%rip), %rdx
movl (%rdx,%rdi,4), %ecx
leaq array1(%rip), %rdx
movl %ecx, (%rdx,%rax,4)
ret
当我阅读汇编代码时,我读到... array2(%rip)
然后我就不知道该如何前进了。
这时,根据我的计算,我应该有 %rdx = %rdi + (%rsi + %rax) + 4*((%rsi+%rax) + 2*(%rsi + %rax))
.
另外,我也不太清楚如何才能从中得到数组的大小。
我通过了,直到
array2(%rip)
然后我就不知道该如何前进了。
使用该指令,地址为 array2
(或 array2[0][0]
)写成了 rdx
注册。忘掉 rip
在这里注册。
该指令加上以下指令的组合(movl
)将读取数组元素 ((int *)array2)[rdi]
. 下面两条指令将写入数组元素 ((int *)array1)[rax]
.
这意味着 rdi
包含的值 M*j+i
和 rax
包含的值 N*i+j
.
如果代码是为System-V编译的。rdi
的值。i
和 rsi
最初包含的值是 j
.
编辑
好吧,我又试了一次,但我不能检索M和N的精确值,因为寄存器没有加载任何值:我是不是遗漏了什么?
首先我们检查 i=0, j=1
:
这意味着 edi
最初 0
和 esi
最初 1
.
如果我没有犯错。rdi
是13之前的 leaq array2 ...
指令。
这意味着 M*j+i = M*1+0 = M = 13
.
然后我们检查 i=1, j=0
.
如果我没有犯错。rax
是9之前的 leaq array2 ...
指令。
这意味着 N*i+j = N*1+0 = N = 9
.
下面是说明,并附有注释,说明它们的作用。
// Initially, edi contains i and esi contains j.
movslq %esi, %rsi // Sign-extended 32-bit j to 64 bits.
movslq %edi, %rdi // Sign-extended 32-bit i to 64 bits.
leaq (%rdi,%rdi,8), %rax // rax = rdi + rdi*8 = 9*rdi = 9*i.
addq %rsi, %rax // rax = rax + rsi = 9*i + j.
leaq (%rsi,%rsi,2), %rdx // rdx = rsi + rsi*2 = 3*rsi = 3*j.
leaq (%rsi,%rdx,4), %rdx // rdx = rsi + rdx*4 = j + (3*j)*4 = 13*j.
addq %rdx, %rdi // rdi = rdi + rdx = i + 13*j = i + 13*j.
leaq array2(%rip), %rdx // rdx = array2 (address of first element).
movl (%rdx,%rdi,4), %ecx // Load *(rdx + rdi*4) = array2[rdi] = array2[i + 13*j] into ecx.
leaq array1(%rip), %rdx // rdx = array1 (address of first element).
movl %ecx, (%rdx,%rax,4) // Store ecx into (rdx + rax*4) = array1[rax] = array1[9*i + j].
因此 array2[j][i]
在C代码中是 array2[i + 13*j]
汇编代码中(考虑到二维寻址和一维寻址)。后者应该是 array2[i + M*j]
因此,我们可以得出结论 M
是13。
同样地: array1[i][j]
在C代码中是 array1[9*i + j]
汇编代码中。后者应该是 array1[N*i + j]
因此,我们可以得出结论 N
是9。