This is aarch64 assembly language program. Write sum_array function recursively. 
It should have 3 parameters: 1. address of dup array 2. startidx 3. stopidx.
It should save parameters into stack pointer before calling recursive function itself and retrieve it after recursive function call.
Have base case and recursive case.
.section .rodata
    getnstr: .string "Enter a value of n: "
    .align 3
    origstr: .string "The original array is:\n"
    .align 3
    dupstr: .string "\n\nThe sorted duplicate array is:\n"
    .align 3
    dupstr2: .string "\n\nThe average of the duplicate array is: "
    intstr: .string "%d"
    .align 3
    tab10dintstr: .string "%5d"
    .align 3
    nlstr: .string "\n"
    .align 3


.section .bss
	n: .skip 4
	n16: .skip 4

.section .text
.global main
.type main, @function

main:
	stp x29, x30, [sp, #-16]! // main prolog
	
	// Generate a seed to be used by srand and set the seed for the random number generator
	mov x0, 0
	bl time
	bl srand
	
	// prompt the user to enter their TCU id number
	ldr x0, =getnstr
	bl printf
	ldr x0, =intstr
	ldr x1, =n
	bl scanf
	
	// Check if the TCU id number is even
	ldr x0, =n
	and x0, x0, #1
	cmp x0, #0
	beq even
	
	mov x0, #33
	ldr x1, =n
	str x0, [x1]
	b endgetnstr

even:
	mov x0, #42
	ldr x1, =n
	str x0, [x1]
	
endgetnstr:
	// compute next highest multiple of 16 that is bigger or equal to n
	adr x1, n
	ldr w1, [x1]
	sbfiz x1, x1, #2, #20
	add x1, x1, #0xf
	and x1, x1, #0xfffffffffffffff0
	adr x2, n16
	str w1, [x2]
	
	// create the storage for “n” integers (namely orig array) on stack pointer
	sub sp, sp, x1
	
	// call init_array
	mov x0, sp // move address of orig array to x0
	bl init_array
	
	// print orig array
	ldr x0, =origstr
	bl printf
	mov x0, sp
	bl print_array
	
	// create the storage for “n” integers (namely dup array) on stack pointer
	adr x2, n16
	ldr w2, [x2]
	sub sp, sp, x2
	
	// call copy_array
	mov x0, sp // address of dup array
	add x1, sp, x2 // address of orig array
	bl copy_array
	
	// call insertion_sort
	mov x0, sp // address of dup array
	bl insertion_sort
	
	// print dup array
	ldr x0, =dupstr
	bl printf
	mov x0, sp
	bl print_array
	ldr x0, =nlstr
	bl printf
	
	// call compute_average
	ldr x0, =dupstr2
	bl printf
	mov x0, sp // address of dup array
	bl compute_average
	
	// print out the average to standard output
	ldr x0, =intstr
	bl printf

	// restore storage for “n” integers (namely dup array) on stack pointer
	adr x1, n16
	ldr x1, [x1]
	add sp, sp, x1
	
	// restore storage for “n” integers (namely orig array) on stack pointer
	adr x1, n16
	ldr x1, [x1]
	add sp, sp, x1
	
	ldp x29, x30, [sp], #16 // main epilog
	mov x0, #0
	ret

.type init_array, @function
init_array:
	stp x29, x30, [sp, #-16]! //function prolog
	
	mov x19, #0 // loop counter
	ldr x20, =n
	ldr w20, [x20]
	mov x21, x0
	
loop1:
	cmp x19, x20
	bge endloop1
	
	// save random value to sp array
	bl rand
	and w0, w0, #255
	str w0, [x21, x19, lsl 2]
	
	add x19, x19, #1
	b loop1

endloop1:
	ldp x29, x30, [sp], #16 //function epilog
	ret

.type print_array, @function
print_array:
	stp x29, x30, [sp, #-16]! //function prolog
	
	mov x19, #0 // loop counter
	ldr x20, =n
	ldr w20, [x20]
	mov x21, x0
	
loop2:
	// restore x1, x2 from sp
	cmp x19, x20
	bge endloop2
	
	ldr x0, =tab10dintstr
	ldr w1, [x21, x19, lsl 2]
	bl printf
	
	add x19, x19, #1
	
	// check if x19 is multiple of 5, if yes print nlstr
	mov x22, #5
	sdiv x23, x19, x22
	mul x24, x23, x22
	cmp x24, x19
	bne continue_loop2
	ldr x0, =nlstr
	bl printf

continue_loop2:
	b loop2

endloop2:
	ldp x29, x30, [sp], #16 //function epilog
	ret


.type copy_array, @function
copy_array:
	stp x29, x30, [sp, #-16]! //function prolog
	
	mov x19, #0 // loop counter
	ldr x20, =n
	ldr w20, [x20]
	    mov x21, x1 // address of orig array
    mov x22, x0 // address of dup array
    
loop3:
    cmp x19, x20
    bge endloop3
    
    ldr w23, [x21, x19, lsl 2] // load value from orig array
    str w23, [x22, x19, lsl 2] // store value to dup array
    
    add x19, x19, #1
    b loop3
    
endloop3:
	ldp x29, x30, [sp], #16 //function epilog
	ret

.type compute_average, @function
compute_average:
	stp x29, x30, [sp, #-16]! //function prolog
	
	mov x19, #0 // loop counter
	ldr x20, =n
	ldr w20, [x20]
	mov x21, x0 // address of dup array
	
	mov x1, #0 // startidx = 0
	mov x2, x20 // stopidx = n
	// push x1 and x2 to the stack pointer
	
	bl sum_array
	mov x22, x0 // put result of sum_array

endloop4:
	udiv x1, x22, x20
	ldp x29, x30, [sp], #16 //function epilog
	ret

	

.type sum_array, @function
sum_array:
	stp x29, x30, [sp, #-16]! //function prolog
	
	ldp x29, x30, [sp], #16 //function epilog
	ret

.type insertion_sort, @function
insertion_sort:
	stp x29, x30, [sp, #-16]! // function prolog
	mov x29, sp

	ldr x20, =n
	ldr w20, [x20] // n

	// for i = 1 to n-1
	mov x19, #1
	outer_loop:

	cmp x19, x20
	bge end_outer_loop

	mov x23, x19
	ldr w22, [x0, x23, lsl 2] // key = array[i]

	// for j = i-1; j >= 0 and array[j] > key
	sub x24, x19, #1

inner_loop:
	cmp x24, #0
	blt end_inner_loop

	ldr w25, [x0, x24, lsl 2] // array[j]
	cmp w25, w22
	bls end_inner_loop

	// array[j+1] = array[j]
	add x26, x24, #1
	str w25, [x0, x26, lsl 2]
	sub x24, x24, #1
	b inner_loop

end_inner_loop:
	add x27, x24, #1
	str w22, [x0, x27, lsl 2] // array[j+1] = key

	add x19, x19, #1
	b outer_loop

end_outer_loop:
	ldp x29, x30, [sp], #16 // function epilog
	ret