Calculating Divisors with Q8

This next problem gets a little more mathy, diving into the middle of a real algorithm, finding divisors of a given value. As a limitation of the program, it can produce bad data if i * j > 255. Q8 can only handle values from 0-255, and will overflow if pushed past that maximum. With that in mind, let's dig into our program!

One of the things put in place here is a bit of an early exit to dramatically shorten run time. The check to see if i < j ensures that the code doesn't run past the halfway point and print duplicate divisors. Without the early exit, the code would print 1 12 2 6 3 4 4 3 6 2 12 1, which is a giant waste of time and effort.

One of the things this program doesn't do, is sort the divisor list. That remains as a bonus challenge for the reader. You'll notice that it doesn't need a full sort. Half the values are ascending, and the other half the values are descending. with a little clever array walking code, you could collate the two, only walking the list once or twice.

C-like Program

int input_value = 12;
int candidate = 0;
// I-LOOP
for (int i = 0; i <= input_value; i++) {
    // J-LOOP
    for (int j = 0; j <= input_value; j++) {
		// GET NEXT CANDIDATE
        candidate += i;
        if (candidate == input_value) {
            if (i > j) {
                // EXIT
                return;
            } else {
				// APPEND LIST
                // add i, j to divisor array
            }
        }
    }
    candidate = 0;
}

Bytecode Program

Assembly Program

; I typically jump into real code at the beginning
; like this to give myself scratch-room if I forget
; something, or need a little more space

>0
JMP i-loop ; Hop into actual code

>32
i-loop:
LOAD A i ; Read in i
LOAD B in ; Read in input_value
CMP A B ; Check to see if the loop has finished
JE exit ; goto exit if done
INC A ; i++
STORE A i ; store i
JMP j-loop

>48
j-loop:
LOAD A j ; Read in j
LOAD B in ; Read in input_value
CMP A B ; Check to see if loop has finished
JE j-loop_reset
INC A ; j++
STORE A j ; store j
JMP get_next_candidate ; goto get next candidate

>60
; reset j and candiate to 0
j-loop_reset:
SET A 0
STORE A j ; set j to 0
STORE A candidate ; set candiate to 0
JMP i-loop

>80
get_next_candidate:
LOAD A candidate ; read in candidate
LOAD B i ; read in i
ADD A B ; candidate += i
STORE A candidate ; store new candiate
LOAD B in ; load input_value
CMP A B ; candidate == input_value?
JE append_list
JMP j-loop

>112
append_list:
LOAD A i ; read in i
LOAD B j ; read in j
CMP A B ; i > j?
JG exit
STOREI A idx ; store i to array[n]
STOREI B idx+ ; store j to array[n+1]
LOAD A idx ; load n
LOAD B idx+ ; load n+1
INC A ;
INC A ; n += 2
INC B ;
INC B ; (n+1) += 2
STORE A idx ; store new n
STORE B idx+ ; store new n+1
JMP j-loop

>255
exit:
HALT

; DATA
>176
idx: $224
idx+: $225
>192
in: $12
i: $0
j: $0
candidate: $0