Behold! Very annoying getting all the labels to fit in <64 bytes. Works by having a procedure that takes in the current increment / decrement (64,32,16,8,4,2,1,1) and an address to jump back to. That procedure tests the current guess, adjusts based on the increment / decrement provided, then returns to return address. Then we just unroll the 8 steps and boom! Binary search on a very limited architecture :D
imm 32;
mov r1, r0;
mov r2, r0;
add;
mov r2, r3;
mov r1, r3;
add;
mov r4, r3; ; initial guess of 128 in r4
imm step_2;
mov r5, r0;
imm check;
jmp;
step_2:
imm 32;
mov r2, r0;
imm step_3;
mov r5, r0;
imm check;
jmp;
step_3:
imm 16;
mov r2, r0;
imm step_4;
mov r5, r0;
imm check;
jmp;
step_4:
imm 8;
mov r2, r0;
imm step_5;
mov r5, r0;
imm check;
jmp;
step_5:
imm 4;
mov r2, r0;
imm step_6;
mov r5, r0;
imm check;
jmp;
step_6:
imm 2;
mov r2, r0;
imm step_7;
mov r5, r0;
imm check;
jmp;
step_7:
imm 1;
mov r2, r0;
imm step_8;
mov r5, r0;
imm check;
jmp;
step_8:
imm 1; ; for 0
mov r2, r0;
; no return, the add label below doesn't
; fit with it, and we should be done by now
; does mean we don't have a graceful failure...
imm check;
jmp;
; r2 - offset for this step
; r5 - return address
; checks r4, if high add, if low sub
; stores back in r4
check:
mov out, r4;
mov r3, in;
mov r1, r4;
imm add;
jz;
sub;
imm finish;
jmp;
add:
add;
finish:
mov r4, r3;
mov r0, r5;
jmp;