Reputation:
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
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