user15339735
user15339735

Reputation:

Converting c code into assembly for arrays

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

Answers (1)

Ammar Faizi
Ammar Faizi

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.

Fix for this

I reworked your Assembly code.

func.S


.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

main.c


#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); 
}

Execution

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

Related Questions