Introduction

Hello World

Printing variables

User input

Testing printf

Mathematical operations

Functions

Arrays

Loops

The stack

Projects:

Estimating sin(x)

Calculating cube roots

Sieve of Eratosthenes

Quadratic Solver

Solving quadratics using the quadratic equation

The quadratic equation is given as:

x = - b ± b 2 - 4 a c 2 a

How to do it.

RegisterPurpose
d0a coefficient
d1b coefficient
d2c coefficient
d3-b
d4b2 & root 1
d54ac & root 2
d62a
d7b2-4ac
d8x(n)
d9x(n+1)

The process requires calculating a square root. This will be done using the same method for calculating cube roots shown on the cube roots page. That is, the Newton-Raphson method.

The derivation of the square root formula is the same process as for the cube root. Only the outcome is different so I'll skip to the end and say that the estimate of the square root is given by:

x n+1 = 1 2 ( x n + N x n )

Unlike the cube root calculation, this one is very straight forward. The pseudocode looks like:

It is accomplished with this code:

  
    root_loop:
	  fdiv d9, d7, d8	// d9 = N/x(i)
  	  fadd d9, d9, d8 // d9 = x(i) + N/x(i)
	  fmov d10, #2
	  fdiv d9, d9, d10	//d9 = 1/2(x(i) + N/x(i))
	  fcmp d8, d9
	  B.EQ final_calc
	  fmov d8, d9
	  b root_loop
  

The registers being used here are:

RegisterPurpose
d7N [=sqrt(b2-4ac)]
d8Estimate of x(n)
d9x(n+1)
d102. Used to perform /2

Source Code

  
    // quadratic1.s
// An app to solve quadratic equations of the form ax^2 + bx +c
// where a, b, c are integers

.global main
.extern scanf
.extern printf

.data
a_input_msg:
	.asciz "Value for a: "
b_input_msg:
	.asciz "Value for b: "
c_input_msg:
	.asciz "Value for c: "
a_fmt:
	.asciz "%lf"
b_fmt:
	.asciz "%lf"
c_fmt:
	.asciz "%lf"
a:
	.double 0
b:
	.double 0
c:
	.double 0
output_message:
	.asciz "%lfx^2 + %lfx + %lf = (x + %lf)(x + %lf)\n"
no_roots_output:
	.asciz "No real roots.\n"
test_output:
	.asciz "a = %lf, b = %lf, c = %lf\n"

.text
main:
	// prolog
	stp x29, x30, [sp, -16]!
	mov x29, sp

	// main code
	ldr x0, =a_input_msg
	bl printf
	ldr x0, =a_fmt
	ldr x1, =a
	bl scanf

	ldr x0, =b_input_msg
	bl printf
	ldr x0, =b_fmt
	ldr x1, =b
	bl scanf

	ldr x0, =c_input_msg
	bl printf
	ldr x0, =c_fmt
	ldr x1, =c
	bl scanf

test:
	ldr x0, =test_output
	ldr x1, =a
	ldr d0, [x1]	// a in d0
	ldr x2, =b
	ldr d1, [x2]	// b in d1
	ldr x3, =c
	ldr d2, [x3]	// c in d2
//	bl printf

	fneg d3, d1	// -b in d3

	fmul d4, d1, d1	// b^2 in d4

	fmul d5, d0, d2	// a*c in d5
	fmov d6, #4
	fmul d5, d5, d6	// 4ac in d5

	fadd d6, d0, d0	// 2a in d6

	fcmp d4, d5
	B.LT no_roots

	fsub d7, d4, d5	// b^2 - 4ac in d7

	fmov d8, #4
	fdiv d8, d7, d8	// new estimate for x(n)

root_loop:
	fdiv d9, d7, d8	// d9 = N/x(i)
	fadd d9, d9, d8 // d9 = x(i) + N/x(i)
	fmov d10, #2
	fdiv d9, d9, d10	//d9 = 1/2(x(i) + N/x(i))
	fcmp d8, d9
	B.EQ final_calc
	fmov d8, d9
	b root_loop

final_calc:
	fadd d4, d3, d8	// -b + sqrt
	fdiv d4, d4, d6	// /2a.  d4 now has first root

	fsub d3, d3, d8	// -b - sqrt
	fdiv d3, d3, d6	// /2a.  d3 now has second root

	ldr x0, =output_message
	bl printf
	b end
no_roots:
	ldr x0, =no_roots_output
	bl printf

end:
	// clean up
	mov x0, #0
	ldp x29, x30, [sp], 16
	RET