装配指令阅读,leaq

问题描述 投票:0回答:1

所以我想用下面的代码与给出的汇编代码计算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)).

另外,我也不太清楚如何才能从中得到数组的大小。

c assembly x86-64
1个回答
1
投票

我通过了,直到 array2(%rip) 然后我就不知道该如何前进了。

使用该指令,地址为 array2 (或 array2[0][0])写成了 rdx 注册。忘掉 rip 在这里注册。

该指令加上以下指令的组合(movl)将读取数组元素 ((int *)array2)[rdi]. 下面两条指令将写入数组元素 ((int *)array1)[rax].

这意味着 rdi 包含的值 M*j+irax 包含的值 N*i+j.

如果代码是为System-V编译的。rdi 的值。irsi 最初包含的值是 j.

编辑

好吧,我又试了一次,但我不能检索M和N的精确值,因为寄存器没有加载任何值:我是不是遗漏了什么?

首先我们检查 i=0, j=1:

这意味着 edi 最初 0esi 最初 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.


4
投票

下面是说明,并附有注释,说明它们的作用。

// 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。

© www.soinside.com 2019 - 2024. All rights reserved.