This is an emulator for Dick, my 16-bit one instruction set computer.
Δt: 50ms (20fps) | |
A line of an assembly programme is either a label, a value, or an instruction.
Labels end in ':'s, and mark the name preceding the ':' as referring to that location in memory.
A value is either an integer literal like 413, 0x98ab, etc. or a label name. The latter can optionally be preceded by a '-' to indicate that it should be the value of that label minus one (which is useful for setting the PC).
Instructions are all MOV A B, since it's an OISC. A and B are both 8-bit addresses, and can optionally be values (as long as those values fit in 8 bits). Nicknames for words can also be used (e.g. OPA instead of W01).
';' starts a comment.
This one only works if you run it on the actual computer, not this emulator, and then look at the display upside-down.
MOV HELLO OUTPUT LOOP: MOV LOOP_PTR PC LOOP_PTR: -LOOP HELLO: 7734
START: MOV SQUARE W0B MOV SIDES W01 MOV TWO W02 MOV W00 SIDES MOV SIDES W01 MOV SQUARE W02 MOV W00 SQUARE MOV STARTPTR W00 SIDES: 1 SQUARE: 1 TWO: 2 STARTPTR: -START
This uses bit-shifts to test divisors quickly. It also only tests divisors up to the square root of the candidate prime. You can make it much faster, at the expense of reducing how long it lasts before getting inaccurate, by removing some of the "MOV SLA SLA" lines.
; TEST PRIME P TEST_PRIME: MOV THREE Q MOV NINE QSQUARED TEST_DIVISOR: MOV Q SLA MOV SLA SLA MOV SLA SLA MOV SLA SLA MOV SLA SLA MOV SLA SLA MOV SLA SLA MOV SLA SLA MOV SLA SRA ; SRA = Q << 8 MOV MINUS_P DIVACC DIVLOOP: MOV DIVACC OPB MOV SRA OPA MOV SUB_PTR CARA MOV DONTSUB_PTR CARB MOV CARB PC SUB: MOV ABSUM DIVACC MOV NEXTSHIFT_PTR PC DONTSUB: ; IF OPB + SRA == 0, P IS COMPOSITE MOV ABSUM OPB MOV ZERO OPA MOV NEXTP_PTR EQUA ; DIVISOR FOUND MOV NEXTSHIFT_PTR EQUB MOV EQUB PC NEXTSHIFT: MOV SRA OPA MOV Q OPB MOV SRA SRA MOV NEXTQ_PTR EQUA MOV DIVLOOP_PTR EQUB MOV EQUB PC NEXTQ: MOV Q OPA MOV TWO OPB MOV ABSUM Q MOV OPA SLA MOV SLA SLA MOV SLA OPA MOV THREE OPB MOV ABSUM OPA MOV QSQUARED OPB MOV ABSUM OPA MOV OPA CARA ; CARA STORES Q SQUARED MINUS ONE ; CARA IS USED AS A TEMP VARIABLE HERE MOV ONE OPB MOV ABSUM QSQUARED ; Q AND QSQUARED HAVE NOW PROGRESSED ; IF Q**2 - P > 0 GOTO NEXTP ; IF (Q**2 - 1) - P >= 0 GOTO NEXTP MOV CARA OPA MOV MINUS_P OPB MOV TEST_DIVISOR_PTR CARA MOV PRIME_FOUND_PTR CARB MOV CARB PC PRIME_FOUND: MOV P OUTPUT NEXTP: MOV P OPA MOV TWO OPB MOV ABSUM P MOV MINUS_P OPA MOV MINUS_TWO OPB MOV ABSUM MINUS_P MOV TEST_PRIME_PTR PC Q: 0 QSQUARED: 0 P: 9 MINUS_P: 0XFFF7 ; -9 ONE: 1 TWO: 2 MINUS_TWO: 0XFFFE THREE: 3 NINE: 9 ZERO: 0 DIVACC: 0 ; POINTERS TEST_PRIME_PTR: -TEST_PRIME TEST_DIVISOR_PTR: -TEST_DIVISOR DIVLOOP_PTR: -DIVLOOP SUB_PTR: -SUB DONTSUB_PTR: -DONTSUB NEXTSHIFT_PTR: -NEXTSHIFT NEXTQ_PTR: -NEXTQ PRIME_FOUND_PTR: -PRIME_FOUND NEXTP_PTR: -NEXTP