a_size = 4				// size of var a
b_size = 4				// size of var b
alloc = -(16 + a_size + b_size) & -16	// memory to allocate on stack
dealloc = -alloc			// memory to deallocate from stack
a_s = 16				// offset for var a from fp
b_s = 20				// offset for var b from fp

	// printf string formats
fmt:	.string	"a: %d\nb: %d\n"
fmtSwap:.string "---Swapping a and b---\n"


	.balign 4
	.global main
main:	stp	x29, x30, [sp, alloc]!
	mov	x29, sp

	// Initialize a and b
	mov	w19, 5		// init a to 5
	str	w19, [x29, a_s]
	mov	w20, 7		// init b to 5
	str	w20, [x29, b_s]

	// Print a and b before the swap
	adrp	x0, fmt
	add	x0, x0, :lo12:fmt
	ldr	w1, [x29, a_s]	// load VALUE of a
	ldr	w2, [x29, b_s]	// load VALUE of b
	bl	printf

	// Tell user we're swapping a and b now
	adrp	x0, fmtSwap
	add	x0, x0, :lo12:fmtSwap
	bl	printf

	// Swap a and b by passing both variables as pointers to the swap(x,y) subroutine
	add	x0, x29, a_s	// load POINTER to a as arg1
	add	x1, x29, b_s	// load POINTER to b as arg2
	bl swap

	// Print a and b again after the swap
	adrp	x0, fmt
	add	x0, x0, :lo12:fmt
	ldr	w1, [x29, a_s]	// load VALUE of a
	ldr	w2, [x29, b_s]	// load VALUE of b
	bl	printf

	mov	w0, 0

	ldp	x29, x30, [sp], dealloc
	ret


swap:	stp	x29, x30, [sp, -16]!
	mov	x29, sp

	// x0 and x1 are addresses
	// in main, we calculated x0 = x29 + a_s
	// in main, we calculated x1 = x29 + b_s

	// 1. load values from the two addresses
	// 2. store the swapped values back to the to addresses
	ldr	w9, [x0]		// w9 = *x
	ldr	w10, [x1]		// w10 = *y
	str	w10, [x0]		// *x = w10
	str	w9, [x1]		// *y = w9

	// We don't need a return value, since we swapped the variables directly in memory

	ldp	x29, x30, [sp], 16
	ret
