Reputation:
So I'm trying to compute the values of M and N in the following code with the assembly code given.
int array1[M][N];
int array2[N][M];
void copyelement(int i, int j) {
array1[i][j] = array2[j][i];
}
Assembly:
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
While reading through the assembly code, I got through till array2(%rip)
and then I didn't know how to move forward.
At this point, according to my calculations I should have
%rdx = %rdi + (%rsi + %rax) + 4*((%rsi+%rax) + 2*(%rsi + %rax))
.
Also I'm not quite sure how I would be able to get the array size from this.
Upvotes: 2
Views: 2923
Reputation: 222669
Here are the instructions with annotations saying what they do.
// Initially, edi contains i and esi contains j.
movslq %esi, %rsi // Sign-extend 32-bit j to 64 bits.
movslq %edi, %rdi // Sign-extend 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].
Thus array2[j][i]
in the C code is array2[i + 13*j]
in the assembly code (making allowances for two-dimensional addressing versus one-dimensional addressing). The latter should be array2[i + M*j]
, so we can conclude M
is 13.
Similarly, array1[i][j]
in the C code is array1[9*i + j]
in the assembly code. The latter should be array1[N*i + j]
, so we can conclude N
is 9.
Upvotes: 4
Reputation: 18493
I got through till
array2(%rip)
and then I didn't know how to move forward.
Using that instruction, the address of array2
(or array2[0][0]
) is written to the rdx
register. Forget about the rip
register here.
The combination of that instruction plus the following one (movl
) will read the array element ((int *)array2)[rdi]
. The two instructions following will write the array element ((int *)array1)[rax]
.
This means that rdi
contains the value M*j+i
and rax
contains the value N*i+j
.
If the code has been compiled for System-V, rdi
initally contained the value of i
and rsi
initially contained the value of j
.
EDIT
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?
First we check with i=0, j=1
:
This means that edi
is initially 0
and esi
is initially 1
.
If I did not make a mistake, rdi
is 13 before the leaq array2 ...
instruction.
This means that M*j+i = M*1+0 = M = 13
.
Then we check with i=1, j=0
.
If I did not make a mistake, rax
is 9 before the leaq array2 ...
instruction.
This means that N*i+j = N*1+0 = N = 9
.
Upvotes: 1