汇编指令阅读,leaq
Assembly instruction reading, leaq
因此我尝试使用给定的汇编代码计算以下代码中 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))
.
我也不太确定如何从中获取数组大小。
I got through till array2(%rip)
and then I didn't know how to move forward.
使用该指令,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
的值。
编辑
okay I tried again, but I can't retrieve the exact value of M and N because the registers don't have any values loaded :/ am I missing something?
首先我们检查 i=0, j=1
:
这意味着 edi
最初是 0
而 esi
最初是 1
。
如果我没记错的话,rdi
在leaq array2 ...
指令之前是13。
这意味着M*j+i = M*1+0 = M = 13
.
然后我们用i=1, j=0
检查一下。
如果我没记错的话,rax
在leaq array2 ...
指令之前是9。
这意味着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].
因此,C 代码中的 array2[j][i]
是汇编代码中的 array2[i + 13*j]
(考虑到二维寻址与一维寻址)。后者应该是array2[i + M*j]
,所以我们可以得出M
是13.
同理,C代码中的array1[i][j]
就是汇编代码中的array1[9*i + j]
。后者应该是array1[N*i + j]
,所以我们可以得出结论N
是9.
因此我尝试使用给定的汇编代码计算以下代码中 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))
.
我也不太确定如何从中获取数组大小。
I got through till
array2(%rip)
and then I didn't know how to move forward.
使用该指令,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
的值。
编辑
okay I tried again, but I can't retrieve the exact value of M and N because the registers don't have any values loaded :/ am I missing something?
首先我们检查 i=0, j=1
:
这意味着 edi
最初是 0
而 esi
最初是 1
。
如果我没记错的话,rdi
在leaq array2 ...
指令之前是13。
这意味着M*j+i = M*1+0 = M = 13
.
然后我们用i=1, j=0
检查一下。
如果我没记错的话,rax
在leaq array2 ...
指令之前是9。
这意味着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].
因此,C 代码中的 array2[j][i]
是汇编代码中的 array2[i + 13*j]
(考虑到二维寻址与一维寻址)。后者应该是array2[i + M*j]
,所以我们可以得出M
是13.
同理,C代码中的array1[i][j]
就是汇编代码中的array1[9*i + j]
。后者应该是array1[N*i + j]
,所以我们可以得出结论N
是9.