user22437801
user22437801

Reputation:

Separating array with ARMv8 assembly code

I need help with my assembly code it is supposed to split an array into two arrays. One stores prime numbers, and the other stores composites. There is C code that does this with the "primeIterator" function but i need to link another file containing ARMv8 assembly code that does the same thing. I've attached the code that i use to run/debug and the assembly code file bellow it, when i debug the first file i recieve an svc.h error (Source not found). I am using Oracle VM virtualbox and within that i am using DS-5. I have a breakpoint at "return 1" and "return 0" in the first file. I'm not sure why im recieving this error. I added the output of the commands tab, this may help you understand the issue.I asked chatgpt about the issue and it believes that a semihosting call was made, and the system is halting due to an unhandled semihosting operation and im not sure why this would be occuring. Also, i'd like to add that it is definitely an issue with the assembly code because when i uncomment the C code function the file works correctly separating the arrays.

#include <stdio.h>

extern void isPrimeAssembly(unsigned long long a[], unsigned long long prime[], unsigned long     long composite[], unsigned long long len);

unsigned long long isPrime(unsigned long long n)
{
    unsigned long long i;
    //prime test. if d is 1, number is prime. if d is 0, number is composite
    for(i=2; i <= n/2; ++i)
    {
        if(n % i == 0)
        {
            return 0;
        }
    }
    return 1;

}

void primeIterator(unsigned long long a[], unsigned long long prime[], unsigned long long     composite[], unsigned long long len){
    unsigned long long i = 0, j = 0, k = 0; //array indices
    unsigned long long d = 0; //will be a one or zero. Was it prime or composite?
    unsigned long long temp = 0; //holds one element of the test array

    //iterate over elements of a, checking if each is prime
    for( i = 0; i < len; i++) {
        //initialize current element of a we are operating on
        d = isPrime(a[i]);


        if(d == 1){
            prime[j] = a[i];
            j++;
        }
        else{
            composite[k] = a[i];
            k++;
        }
    }
    return;

}


int main(){
    //initialize test and result arrays
    unsigned long long arrayLength = 16;
    unsigned long long a[] = {7, 16, 23, 40, 11, 39, 37, 10, 2, 18, 44, 83, 87, 5, 6, 11};
    unsigned long long prime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned long long composite[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};


    //primeIterator(a, prime, composite, arrayLength);
    isPrimeAssembly(a, prime, composite, arrayLength);

    printf("Input Array elements were: ");
    for(int i = 0; i < arrayLength; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");

    printf("Prime Array elements are: ");
    for(int i = 0; i < arrayLength; i++)
    {
        printf("%d ", prime[i]);
    }
    printf("\n");

    printf("Composite Array elements are: ");
    for(int i = 0; i < arrayLength; i++)
    {
        printf("%d ", composite[i]);
    }
    printf("\n");
    return 0;
}



-------------------------------------------------------------------

.globl isPrimeAssembly
isPrimeAssembly:
    // Save callee-saved registers
    sub sp, sp, #32 // Make space for 4 registers
    stp x19, x20, [sp, #0]
    stp x21, x22, [sp, #16]

    mov x19, #0 // i counter for outer loop
    mov x20, #0 // j counter for prime array
    mov x21, #0 // k counter for composite array

outer_loop:
    cmp x19, x3 // compare i with len
    b.ge end_outer_loop

    ldr x22, [x0, x19, lsl #3] // load a[i] into x22
    bl isPrime // call isPrime function, result in x0
    cbnz x0, is_prime // if result is 1, go to is_prime

    //Not Prime
    str x22, [x2, x21, lsl #3] // store a[i] in composite[k]
    add x21, x21, #1 // increment k
    b continue_outer_loop

is_prime:
    //Prime
    str x22, [x1, x20, lsl #3] // store a[i] in prime[j]
    add x20, x20, #1 // increment j

continue_outer_loop:
    add x19, x19, #1 // increment i
    b outer_loop

end_outer_loop:
    // Restoring callee-saved registers
    ldp x21, x22, [sp, #16]
    ldp x19, x20, [sp, #0]
    add sp, sp, #32 // Restore the stack pointer
    ret

isPrime:
    //Your code for detecting a prime number here
    // x0 holds the number to be tested
    mov x19, #2 // i counter
    mov x20, x0, lsr #1 // x20 = n/2

isPrime_loop:
    cmp x19, x20
    b.ge end_isPrime_loop

    //Checking if n % i == 0
    udiv x21, x0, x19 // x21 = n / i
    msub x21, x21, x19, x0 // x21 = n - (n/i)*i
    cbz x21, composite

    add x19, x19, #1 // increment i
    b isPrime_loop

end_isPrime_loop:
    mov x0, #1 // return 1 (prime)
    ret

composite:
    mov x0, #0 // return 0 (composite)
    ret
-------------------------------------------------------------------

Commands Tab:

In svc.h Unable to read source file /home/tcwg-buildslave/workspace/tcwg-make-release/builder_arch/i386/label/tcwg-x86_64-build/target/aarch64-elf/snapshots/newlib.git~linaro-local~linaro-newlib-2_5_0/libgloss/aarch64/svc.h EL3:0x000000008002C658 89,0 HLT #0xf000

I was expecting the array to be separated into two arrays, one with all the prime numbers and another with all the composite numbers.
-------------------------------------------------------------------

.globl isPrimeAssembly
isPrimeAssembly:
    // Save callee-saved registers
    sub sp, sp, #32 // Make space for 4 registers
    stp x19, x20, [sp, #0]
    stp x21, x22, [sp, #16]

    mov x19, #0 // i counter for outer loop
    mov x20, #0 // j counter for prime array
    mov x21, #0 // k counter for composite array

outer_loop:
    cmp x19, x3 // compare i with len
    b.ge end_outer_loop

    ldr x22, [x0, x19, lsl #3] // load a[i] into x22
    bl isPrime // call isPrime function, result in x0
    cbnz x0, is_prime // if result is 1, go to is_prime

    //Not Prime
    str x22, [x2, x21, lsl #3] // store a[i] in composite[k]
    add x21, x21, #1 // increment k
    b continue_outer_loop

is_prime:
    //Prime
    str x22, [x1, x20, lsl #3] // store a[i] in prime[j]
    add x20, x20, #1 // increment j

continue_outer_loop:
    add x19, x19, #1 // increment i
    b outer_loop

end_outer_loop:
    // Restoring callee-saved registers
    ldp x21, x22, [sp, #16]
    ldp x19, x20, [sp, #0]
    add sp, sp, #32 // Restore the stack pointer
    ret

isPrime:
    //Your code for detecting a prime number here
    // x0 holds the number to be tested
    mov x19, #2 // i counter
    mov x20, x0, lsr #1 // x20 = n/2

isPrime_loop:
    cmp x19, x20
    b.ge end_isPrime_loop

    //Checking if n % i == 0
    udiv x21, x0, x19 // x21 = n / i
    msub x21, x21, x19, x0 // x21 = n - (n/i)*i
    cbz x21, composite

    add x19, x19, #1 // increment i
    b isPrime_loop

end_isPrime_loop:
    mov x0, #1 // return 1 (prime)
    ret

composite:
    mov x0, #0 // return 0 (composite)
    ret
------------------------------------------------------------------

Commands Tab:

In svc.h Unable to read source file /home/tcwg-buildslave/workspace/tcwg-make-release/builder_arch/i386/label/tcwg-x86_64-build/target/aarch64-elf/snapshots/newlib.git~linaro-local~linaro-newlib-2_5_0/libgloss/aarch64/svc.h EL3:0x000000008002C658 89,0 HLT #0xf000

I was expecting the array to be separated into two arrays, one with all the prime numbers and another with all the composite numbers.

Upvotes: 0

Views: 85

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126110

The parameter registers (x0-x8) are not preserved across calls, so when you call isPrime it clobbers those registers in your function. So when you subsequently go to access your arrays (the base pointers to which are stoted there), you get garbage and crashes

You need to save these values somewhere they won't be clobbered. Either into callee-preserved registers (x19-x28) or in your stack frame.

Since you're also defining isPrime yourself in the assembly code, you could use a different (non-standard) calling convention there and not clobber x0-x3, but the comments (and code) don't do that -- isPrime definitely clobbers x0

Upvotes: 1

Related Questions