Reputation:
I am currently learning how to convert C code into assembly x86 64 bit code. The code I have is:
long add_arrays(long *arr1, long *arr2, unsigned long num, long *result)
{
unsigned long sum = 0, i = 0;
while(i < num) {
result[i] = arr1[i] + arr2[i];
sum = sum + result[i];
i++;
}
return sum;
}
When I convert it into assembly, I get an output of either 0 or an address number. My code is:
.global add_arrays_asm
add_arrays_asm:
xor %r8, %r8
while_start:
cmp %r8, %rdx
jge while_break
movq (%rdi, %r8, 8), %r9
addq (%rsi, %r8, 8), %r9
movq (%rcx, %r8, 8), %r10
movq (%r9, %r8, 8), %rcx
addq (%r10, %r8, 8), %rax
addq (%rcx,%r8, 8), %rax
inc %r8
jmp while_start
while_break:
ret
And the code I'm using to test it is:
printf("Testing add_arrays_asm\n");
long l3[] = {3, 23, 32, 121, 0, 43, 95, 4};
long l4[] = {-823,12,-1222,84834, -328, 0, 9, -1387};
long res1[] = {0, 0, 0, 0, 0, 0, 0, 0};
long sum1 = add_arrays_asm(l3, l4, 8, res1);
int j = 0;
for(j = 0; j < 8; j++) {
printf("%8ld + %8ld = %8ld\n", l3[j], l4[j], res1[j]);
}
printf(" Sum = %ld\n\n", sum1);
I am new to coding in assembly so I cannot find where the code is going wrong. Any help would be appreciated. Thank you.
Upvotes: 1
Views: 335
Reputation: 1459
Your conditional jump isn't correct.
cmp %r8, %rdx
jge while_break
This means
if (rdx >= r8)
break;
So you directly break the loop without calculating anything. Also, you should use jae
instead of jge
for unsigned comparison, as you declared it as unsigned long num
. Though it may not be a problem if the value isn't overflowing max signed integer such that it be negative.
Another thing your load and store don't seem to be correct. Beside that, you better keep memory access minimal, no need to reload from memory if you don't really need it.
Also, you forgot to zero your %rax
, you should have sum = 0
at the beginning of your calculation.
I reworked your Assembly code.
.section .text
.global add_arrays_asm
add_arrays_asm:
#rdi -> arr1
#rsi -> arr2
#rdx -> num
#rcx -> result
#r8 -> i
xorl %r8d, %r8d # i = 0
xorl %eax, %eax # sum = 0
while_start:
cmpq %rdx, %r8 # if (i >= num)
jae while_break # goto while_break
movq (%rdi, %r8, 8), %r9 # r9 = arr1[i]
addq (%rsi, %r8, 8), %r9 # r9 += arr2[i]
movq %r9, (%rcx, %r8, 8) # result[i] = r9
addq %r9, %rax # sum += r9
incq %r8 # i++
jmp while_start # goto while_start
while_break:
ret
#include <stdio.h>
long add_arrays_asm(long *arr1, long *arr2, unsigned long num, long *result);
int main()
{
printf("Testing add_arrays_asm\n");
long l3[] = {3, 23, 32, 121, 0, 43, 95, 4};
long l4[] = {-823,12,-1222,84834, -328, 0, 9, -1387};
long res1[] = {0, 0, 0, 0, 0, 0, 0, 0};
long sum1 = add_arrays_asm(l3, l4, 8, res1);
int j = 0;
for(j = 0; j < 8; j++) {
printf("%8ld + %8ld = %8ld\n", l3[j], l4[j], res1[j]);
}
printf(" Sum = %ld\n\n", sum1);
}
ammarfaizi2@integral:/tmp/testz$ gcc -Wall -Wextra func.S main.c -o main
ammarfaizi2@integral:/tmp/testz$ valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./main
==748530== Memcheck, a memory error detector
==748530== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==748530== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==748530== Command: ./main
==748530==
Testing add_arrays_asm
3 + -823 = -820
23 + 12 = 35
32 + -1222 = -1190
121 + 84834 = 84955
0 + -328 = -328
43 + 0 = 43
95 + 9 = 104
4 + -1387 = -1383
Sum = 81416
==748530==
==748530== HEAP SUMMARY:
==748530== in use at exit: 0 bytes in 0 blocks
==748530== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==748530==
==748530== All heap blocks were freed -- no leaks are possible
==748530==
==748530== For lists of detected and suppressed errors, rerun with: -s
==748530== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
ammarfaizi2@integral:/tmp/testz$
Upvotes: 4