; 64-bit MASM coding problem ; ; thipdar (at) thipdar tod com ; thipdar (at) gmail tod com ; ; April 8, 2015 ; I invite comment. Please keep it constructive. ; ; My ASM skills are rusty and obsolete, would really like help. ; ; Resources inside the Celeron J1800 ; ; Address Space: Flat ; from zero to (2^46)-1 (or 70,386,744,177,663) Physical, ; from zero to (2^64)-1 (or 18,446,744,073,709,551,615) Virtual ; Each (8-bit) byte of memory has its own address ; Software can query the CPUID to find out how much physical memory the CPU can address ; ; Sixteen 64-bit General-Purpose Registers (quadword) ; RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8-R15 ; (Application Note: All of these are used except for RBP and RSP) ; ; Sixteen 32-bit General-Purpose Registers ; EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP, or R8D-R15D ; (these registers are the lower halves of their respective 64-bit counterparts) ; ; Sixteen 16-bit General-Purpose Registers ; AX, BX, CX, DX, SI, DI, SP, BP, or R8W-R15W ; (these registers are the lower halves of their respective 32-bit counterparts) ; (App. Note: While the 64-bit registers may be 'underused' when some of the cell values are small, none of the GP registers are used as 32-bit or 16-bit registers) ; ; Six 16-bit Registers ; ; Segment Registers ; CS, DS, SS, ES, FS and GS ; (App. Note: Segment Registers are generally ignored in 64-bit operations) ; ; RFLAGS Register (64 bits) ; The upper 32 bits of RFLAGS are reserved ; The lower 32 bits of RFLAGS is the same as EFLAGS ; 31 0 reserved ; 30 0 reserved ; 29 0 reserved ; 28 0 reserved ; 27 0 reserved ; 26 0 reserved ; 25 0 reserved ; 24 0 reserved ; 23 0 reserved ; 22 0 reserved ; 21 System Flag (ID) ID Flag ; 20 System Flag (VIP) Virtual Interrupt Pending ; 19 System Flag (VIF) Virtual Interrupt Flag ; 18 System Flag (AC) Alignment Check/Access Control ; 17 System Flag (VM) Virtual-8086 Mode ; 16 System Flag (RF) Resume Flag ; 15 0 reserved ; 14 System Flag (NT) Nested Task ; 13 System Flag (IOPL) I/O Privilege Level ; 12 System Flag (IOPL) I/O Privilege Level ; 11 Status Flag (OF) Overflow Flag ; 10 Control Flag (DF) Direction Flag ; 9 System Flag (IF) Interrupt Enable Flag ; 8 System Flag (TF) Trap Flag ; 7 Status Flag (SF) Sign Flag ; 6 Status Flag (ZF) Zero Flag ; 5 0 reserved ; 4 Status Flag (AF) Auxiliary Carry Flag ; 3 reserved ; 2 Status Flag (PF) Parity Flag ; 1 reserved ; 0 Status Flag (CF) Carry Flag ; ; (App. Note: Other than ZF, the flags are ignored) ; ; RIP (instruction pointer register) (64 bits) ; (App. Note: RIP is ignored) ; ; FPU Registers: ; Eight 80-bit Floating Point Data registers ; ST0 through ST7 ; (App. Note: The FPU is ignored) ; ; Control Register (16 bits) ; ; Status Register (16 bits) ; ; Tag Register (16 bits) ; ; Opcode Register (11 bits) ; ; Floating Point Unit (FPU) Instruction Pointer Register (64 bits) ; ; FPU Data (Operand) Pointer Register (64 bits) ; ; MMX Registers (Eight 64-bit) ; MM0 through MM7 ; (App. Note: MMX Registers are not used) ; ; XMM Registers (Sixteen 128-bit) ; XXM registers are available for Single Instruction Multiple Data (SIMD) instructions ; XMM0 through XMM15 ; (App. Note: XMM Registers are not used) ; ; MXCSR Register (32 Bits) ; (App. Note: Ignored) ; ; Control Registers ; CR0, CR2, CR3, CR4 and CR8 ; (App. Note: only one Control Register is used, CR0) ; ; System table pointer registers ; GDTR, LDTR, IDTR and task register ; (App. Note: Ignored) ; ; Debug Registers ; DR0, DR1, DR2, DR3, DR6, DR7 ; (App. Note: Ignored) ; ; MSR Registers ; (App. Note: Ignored) ; ; RDX:RAX register pair (as 128-bit operand) ; (App. Note: RDX and RAX are used, but as 64-bit registers, not as a single 128-bit register) ; ; ; Presumed Cell arrangement: ; ; A B C ; D E F ; G H I ; ; ; Problem: ; Given that A != B, B != C, C != D, D != E, E != F, F != G, G != H and H != I, ; find A, B, C, D, E, F, G, H and I, such that (A*A)+(B*B)+(C*C) = (D*D)+(E*E)+(F*F) = (G*G)+(H*H)+(I*I) = ; (A*A)+(E*E)+(I*I) = (C*C)+(E*E)+(G*G) = (A*A)+(D*D)+(G*G) = ; (B*B)+(E*E)+(H*H) = (C*C)+(F*F)+(I*I) ; ; ; Notations: ; H1 (Horizontal row 1) is A, B and C ; H2 (Horizontal row 2) is D, E and F ; H3 (Horizontal row 3) is G, H and I ; D1 (Diagonal row 1) is A, E and I ; D2 (Diagonal row 2) is C, E and G ; V1 (Vertical row 1) is A, D and G ; V2 (Vertical row 2) is B, E and H ; V3 (Vertical row 3) is C, F and I ; ; ; Cell assignments: ; ; RDX = Cell A ; R8 = Cell B ; R9 = Cell C ; R10 = Cell D ; R11 = Cell E ; R12 = Cell F ; R13 = Cell G ; R14 = Cell H ; R15 = Cell I ; ; ; Methodology: ; ôBrute Forceö. Test every possible combination of A through I, where each value for A through I ranges from a lower limit (1) to an upper limit (starting at 10 for proof-of-concept). ; ; ; Tests: ; 'Duplicates Trap' ; A v B, A v C, A v D, A v E, A v F, A v G, A v H, A v I, ; B v C, B v D, B v E, B v F, B v G, B v H, B v I, ; C v D, C v E, C v F, C v G, C v H, C v I, ; D v E, D v F, D v G, D v H, D v I, ; E v F, E v G, E v H, E v I, ; F v G, F v H, F v I, ; G v H, G v I, ; H v I ; ; math evaluations ;H1 v H2, H1 v H3, H1 v D1, H1 v D2, H1 v V1, H1 v V2, H1 v V3, ; H2 v H3, H2 v D1, H2 v D2, H2 v V1, H2 v V2, H2 v V3, ; H3 v D1, H3 v D2, H3 v V1, H3 v V2, H3 v V3, ; D1 v D2, D1 v V1, D1 v V2, D1 v V3, ; D2 v V1, D2 v V2, D2 v V3, ; V1 v V2, V1 v V3, ; V2 v V3 ; ; ; Summing three extremely large squares runs a slight risk of overflow (multiplying them together would be much more risky, but in either case the likelihood is small). ; Using the alternating subtract, add, subtract, add approach taken in testing levels 37 through 64 should avoid accumulator overflow/underflow and make the matter moot. ; Care should be taken that UpperLimit does not exceed 2^31, so that when UpperLimit is squared, it does not exceed 2^62. ; Adding three instances of 2^62 should remain below 2^64. ; ; Rather than repeatedly squaring numbers during the math evaluations (which is a significant portion of the code), this program builds a table of squares and references those values as needed. ; This approach should save a tremendous amount of redundant calculation. ; The index is the number in the cell, the table entry for that index is that number squared. ; Because each table entry is eight memory locations long, the index gets scaled up by eight. ; ; During the math evaluations, the variables representing some cells appear on both sides of the equals sign when Horizontal, Diagonal and Vertical rows are being compared. ; Rather than adding these numbers to both sides of the equal sign, the calculations are optimized to ignore these cells which somewhat reduces the processing load. ; ; As UpperLimit grows upwards from 10, the runtime increases in an extraordinary fashion. ; The number of combinations for an UpperLimit of 10 is 10^9, but the number of combinations for an upperLimit of 100 is 100^9, and for an UpperLimit of 1,000, it is 1,000^9. ; For each order of magnitude increase in the UpperLimit the increase in the number of combinations is NINE orders of magnitude. ; Because of this, it may be possible to set UpperLimit so high that it will take many lifetimes for this program to complete. ; ; ; .DATA UpperLimit = 10 ; Set upper limit to 10 .CODE _Start: MOV RDX, UpperLimit MOV RDI, 65535 ; Set base memory for table of squares ; (65535 was picked from air) XOR RCX, RCX ; Zero out the RCX register INC RCX ; set the tableÆs index number to 1 MOV RAX, RCX STOSQ ; make an entry in the table INC RDI ; Bump the memory pointer INC RDI INC RDI INC RDI INC RDI INC RDI INC RDI INC RDI DCR RDX ; Count one table entry done BuildTable: INC RCX ; bump the index number MOV RBX, RCX ; copy it to RBX MOV RAX, RBX * RBX ; move the square of the index into RAX STOSQ ; make an entry in the table INC RDI ; Bump the memory pointer INC RDI INC RDI INC RDI INC RDI INC RDI INC RDI INC RDI DCR RDX ; Count one table entry done JNZ BuildTable ; Go back until RDX = 0 ; ; Table should be built by this point ; ; Time to initialize the cells ; XOR RDX, RDX ; Zero out the cell INC RDX ; Set Cell A to 1 MOV R8, RDX ; Set Cell B to 1 MOV R9, R8 ; Set Cell C to 1 MOV R10, R9 ; Set Cell D to 1 MOV R11, R10 ; Set Cell E to 1 MOV R12, R11 ; Set Cell F to 1 MOV R13, R12 ; Set Cell G to 1 MOV R14, R13 ; Set Cell H to 1 MOV R15, R14 ; Set Cell I to 1 ; ; Start the grinder ; XOR CR0 ; Set the control register to false .REPEAT ; ; Save the index values ; PUSH RDX PUSH R8 PUSH R9 PUSH R10 PUSH R11 PUSH R12 PUSH R13 PUSH R14 PUSH R15 ; ; Load the cells from the table ; ; The value in the cell acts as an index to the table of squares, except that the index needs to be scaled up by eight (since each register holds eight bytes). ; ; Put the value of the cell (times eight) into the RSI register, use it as a pointer to read the value from the table of squares; invoking LODSQ puts the result from the table into RAX. ; ; RAX then gets moved into the cell, so each cell gets the square of the index ; MOV RSI, RDX * 8 LODSQ MOV RDX, RAX MOV RSI, R8 * 8 LODSQ MOV R8, RAX MOV RSI, R9 * 8 LODSQ MOV R9, RAX MOV RSI, R10 * 8 LODSQ MOV R10, RAX MOV RSI, R11 * 8 LODSQ MOV R11, RAX MOV RSI, R12 * 8 LODSQ MOV R12, RAX MOV RSI, R13 * 8 LODSQ MOV R13, RAX MOV RSI, R14 * 8 LODSQ MOV R14, RAX MOV RSI, R15 * 8 LODSQ MOV R15, RAX ; ; Run the duplicates trap ; ; Move a cell's value into RAX and compare the next cell's value. ; If they are the same, it should set ZF ; MOV RAX, RDX CMP R8 ; Nesting level 1 JZ IsDuplicate CMP R9 ; 2 JZ IsDuplicate CMP R10 ; 3 JZ IsDuplicate CMP R11 ; 4 JZ IsDuplicate CMP R12 ; 5 JZ IsDuplicate CMP R13 ; 6 JZ IsDuplicate CMP R14 ; 7 JZ IsDuplicate CMP R15 ; 8 JZ IsDuplicate MOV RAX, R8 CMP R9 ; 9 JZ IsDuplicate CMP R10 ; 10 JZ IsDuplicate CMP R11 ; 11 JZ IsDuplicate CMP R12 ; 12 JZ IsDuplicate CMP R13 ; 13 JZ IsDuplicate CMP R14 ; 14 JZ IsDuplicate CMP R15 ; 15 JZ IsDuplicate MOV RAX, R9 CMP R10 ; 16 JZ IsDuplicate CMP R11 ; 17 JZ IsDuplicate CMP R12 ; 18 JZ IsDuplicate CMP R13 ; 19 JZ IsDuplicate CMP R14 ; 20 JZ IsDuplicate CMP R15 ; 21 JZ IsDuplicate MOV RAX, R10 CMP R11 ; 22 JZ IsDuplicate CMP R12 ; 23 JZ IsDuplicate CMP R13 ; 24 JZ IsDuplicate CMP R14 ; 25 JZ IsDuplicate CMP R15 ; 26 JZ IsDuplicate MOV RAX, R11 CMP R12 ; 27 JZ IsDuplicate CMP R13 ; 28 JZ IsDuplicate CMP R14 ; 29 JZ IsDuplicate CMP R15 ; 30 JZ IsDuplicate MOV RAX, R12 CMP R13 ; 31 JZ IsDuplicate CMP R14 ; 32 JZ IsDuplicate CMP R15 ; 33 JZ IsDuplicate MOV RAX, R13 CMP R14 ; 34 JZ IsDuplicate CMP R15 ; 35 JZ IsDuplicate MOV RAX, R14 CMP R15 ; 36 JZ IsDuplicate ; ; If any cells have one or more duplicates, control will jump to IsDuplicate at the bottom of the duplicates trap and won't allow this next section to run ; ; ; Time to do some math! ; ; Note that the "=?=" operator is meant to mean "Are these two equal?" ; ; ; start level 37 H1 v H2 ; A, B, C D, E, F ; (A*A)+(B*B)+(C*C) =?= (D*D)+(E*E)+(F*F) ; RDX R8 R9 R10 R11 R12 ; MOV RAX, RDX ; + RDX SBB RAX, R10 ; - R10 ADC RAX, R8 ; + R8 SBB RAX, R11 ; - R11 ADC RAX, R9 ; + R9 SBB RAX, R12 ; - R12 JNZ SumsDifferent ; If the result is zero, test more ; end level 37 ; ; ; start level 38 H1 v H3 ; A, B, C G, H, I ; (A*A)+(B*B)+(C*C) =?= (G*G)+(H*H)+(I*I) ; RDX R8 R9 R13 R14 R15 ; MOV RAX, RDX SBB RAX, R13 ADC RAX, R8 SBB RAX, R14 ADC RAX, R9 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 38 ; ; ; start level 39 H1 v D1 ; A, B, C A, E, I ; optimized (B*B)+(C*C) =?= (E*E)+(I*I) ; R8 R9 R11 R15 ; MOV RAX, R8 SBB RAX, R11 ADC RAX, R9 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 39 ; ; ; start level 40 H1 v D2 ; A, B, C C, E, G ;optimized (A*A)+(B*B) =?= (E*E)+(G*G) ; RDX R8 R11 R13 ; MOV RAX, RDX SBB RAX, R11 ADC RAX, R8 SBB RAX, R13 JNZ SumsDifferent ; If the result is zero, test more ; end level 40 ; ; ; start level 41 H1 v V1 ; A, B, C A, D, G ;optimized (B*B)+(C*C) =?= (D*D)+(G*G) ; R8 R9 R10 R13 ; MOV RAX, R8 SBB RAX, R10 ADC RAX, R9 SBB RAX, R13 JNZ SumsDifferent ; If the result is zero, test more ; end level 41 ; ; ; start level 42 H1 v V2 ; A, B, C B, E, H ;Optimized (A*A)+(C*C) =?= (E*E)+(H*H) ; RDX R9 R11 R14 ; MOV RAX, RDX SBB RAX, R11 ADC RAX, R9 SBB RAX, R14 JNZ SumsDifferent ; If the result is zero, test more ; end level 42 ; ; ; start level 43 H1 v V3 ; A, B, C C, F, I ;optimized (A*A)+(B*B) =?= (F*F)+(I*I) ; RDX R8 R12 R15 ; MOV RAX, RDX SBB RAX, R12 ADC RAX, R8 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 43 ; ; ; start level 44 H2 v H3 ; D, E, F G, H, I ; (D*D)+(E*E)+(F*F) =?= (G*G)+(H*H)+(I*I) ; R10 R11 R12 R13 R14 R15 ; MOV RAX, R10 SBB RAX, R13 ADC RAX, R11 SBB RAX, R14 ADC RAX, R12 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 44 ; ; ; start level 45 H2 v D1 ; D, E, F A, E, I ;optimized (D*D)+(F*F) =?= (A*A)+(I*I) ; R10 R12 RDX R15 ; MOV RAX, R10 SBB RAX, RDX ADC RAX, R12 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 45 ; ; ; start level 46 H2 v D2 ; D, E, F C, E, G ;optimized (D*D)+(F*F) =?= (C*C)+(G*G) ; R10 R12 R9 R13 ; MOV RAX, R10 SBB RAX, R9 ADC RAX, R12 SBB RAX R13 JNZ SumsDifferent ; If the result is zero, test more ; end level 46 ; ; ; start level 47 H2 v V1 ; D, E, F A, D, G ;optimized (E*E)+(F*F) =?= (A*A)+(G*G) ; R11 R12 RDX R13 ; MOV RAX, R11 SBB RAX, RDX ADC RAX, R12 SBB RAX, R13 JNZ SumsDifferent ; If the result is zero, test more ; end level 47 ; ; ; start level 48 H2 v V2 ; D, E, F B, E, H ;optimized (D*D)+(F*F) =?= (B*B)+(H*H) ; R10 R12 R8 R14 ; MOV RAX, R10 SBB RAX, R8 ADC RAX, R12 SBB RAX, R14 JNZ SumsDifferent ; If the result is zero, test more ; end level 48 ; ; ; start level 49 H2 v V3 ; D, E, F C, F, I ;optimized (D*D)+(E*E) =?= (C*C)+(I*I) ; R10 R11 R9 R15 ; MOV RAX, R10 SBB RAX, R9 ADC RAX, R11 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 49 ; ; ; start level 50 H3 v D1 ; G, H, I A, E, I ;optimized (G*G)+(H*H) =?= (A*A)+(E*E) ; R13 R14 RDX R11 ; MOV RAX, R113 SBB RAX, RDX ADC RAX, R14 SBB RAX, R11 JNZ SumsDifferent ; If the result is zero, test more ; end level 50 ; ; ; start level 51 H3 v D2 ; G, H, I C, E, G ;Optimized (H*H)+(I*I) =?= (C*C)+(E*E) ; R14 R15 R9 R11 ; MOV RAX, R14 SBB RAX, R9 ADC RAX, R15 SBB RAX, R11 JNZ SumsDifferent ; If the result is zero, test more ; end level 51 ; ; ; start level 52 H3 v V1 ; G, H, I A, D, G ;optimized (H*H)+(I*I) =?= (A*A)+(D*D) ; R14 R15 RDX R10 ; MOV RAX, R14 SBB RAX, RDX ADC RAX, R15 SBB RAX, R10 JNZ SumsDifferent ; If the result is zero, test more ; end level 52 ; ; ; start level 53 H3 v V2 ; G, H, I B, E, H ;optimized (G*G)+(I*I) =?= (B*B)+(E*E) ; R13 R15 R8 R11 ; MOV RAX, R13 SBB RAX, R8 ADC RAX, R15 SBB RAX, R11 JNZ SumsDifferent ; If the result is zero, test more ; end level 53 ; ; ; start level 54 H3 v V3 ; G, H, I C, F, I ;optimized (G*G)+(H*H) =?= (C*C)+(F*F) ; R13 R14 R9 R12 ; MOV RAX, R13 SBB RAX, R9 ADC RAX, R14 SBB RAX, R12 JNZ SumsDifferent ; If the result is zero, test more ; end level 54 ; ; ; start level 55 D1 v D2 ; A, E, I C, E, G ;optimized (A*A)+(I*I) =?= (C*C)+(G*G) ; RDX R15 R9 R13 ; MOV RAX, RDX SBB RAX, R9 ADC RAX, R15 SBB RAX, R13 JNZ SumsDifferent ; If the result is zero, test more ; end level 55 ; ; ; start level 56 D1 v V1 ; A, E, I A, D, G ;optimized (E*E)+(I*I) =?= (D*D)+(G*G) ; R11 R15 R10 R13 ; MOV RAX, R11 SBB RAX, R10 ADC RAX, R15 SBB RAX, R13 JNZ SumsDifferent ; If the result is zero, test more ; end level 56 ; ; ; start level 57 D1 v V2 ; A, E, I B, E, H ;optimized (A*A)+(I*I) =?= (B*B)+(H*H) ; RDX R15 R8 R14 ; MOV RAX, RDX SBB RAX, R8 ADC RAX, R15 SBB RAX, R14 JNZ SumsDifferent ; If the result is zero, test more ; end level 57 ; ; ; start level 58 D1 v V3 ; A, E, I C, F, I ;optimized (A*A)+(E*E) =?= (C*C)+(F*F) ; RDX R11 R9 R12 ; MOV RAX, RDX SBB RAX, R9 ADC RAX, R11 SBB RAX, R12 JNZ SumsDifferent ; If the result is zero, test more ; end level 58 ; ; ; start level 59 D2 v V1 ; C, W, G A, D, G ;optimized (C*C)+(E*E) =?= (A*A)+(D*D) ; R9 R11 RDX R10 ; MOV RAX, R9 SBB RAX, RDX ADC RAX, R11 SBB RAX, R10 JNZ SumsDifferent ; If the result is zero, test more ; end level 59 ; ; ; start level 60 D2 v V2 ; C, E, G B, E, H ;optimized (C*C)+(G*G) =?= (B*B)+(H*H) ; R9 R13 R8 R14 ; MOV RAX, R9 SBB RAX, R8 ADC RAX, R13 SBB RAX, R14 JNZ SumsDifferent ; If the result is zero, test more ; end level 60 ; ; ; start level 61 D2 v V3 ; C, E, G C, F, I ;optimized (E*E)+(G*G) =?= (F*F)+(I*I) ; R11 R13 R12 R15 ; MOV RAX, R11 SBB RAX, R12 ADC RAX, R13 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 61 ; ; ; start level 62 V1 v V2 ; (A*A)+(D*D)+(G*G) =?= (B*B)+(E*E)+(H*H) ; RDX R10 R13 R8 R11 R14 ; MOV RAX, RDX SBB RAX, R8 ADC RAX, R10 SBB RAX, R11 ADC RAX, R13 SBB RAX, R14 JNZ SumsDifferent ; If the result is zero, test more ; end level 62 ; ; ; start level 63 V1 v V3 ; (A*A)+(D*D)+(G*G) =?= (C*C)+(F*F)+(I*I) ; RDX R10 R13 R9 R12 R15 ; MOV RAX, RDX SBB RAX, R9 ADC RAX, R10 SBB RAX, R12 ADC RAX, R13 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, test more ; end level 63 ; ; ; start level 64 V2 v V3 ; (B*B)+(E*E)+(H*H) =?= (C*C)+(F*F)+(I*I) ; R8 R11 R14 R9 R12 R15 ; MOV RAX, R8 SBB RAX, R9 ADC RAX, R11 SBB RAX, R12 ADC RAX, R14 SBB RAX, R15 JNZ SumsDifferent ; If the result is zero, ; we have achieved success ; end level 64 ; ; ; Restore the index values ; POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP RDX ; ; success processing goes here ; ; The index values represent one set of A, B, C, D, E, F, G, H & I that satisfy the puzzle conditions. ; ; These values should be added to the end of a data file (if it exists; if the file doesn't yet exist, it should be created so that these ; values can be stored in it). ; ; Once the file has been dealt with, we need to let control return to the program so that it can continue to look for other solutions. ; ; Success or failure of the program can be determined by the presence or absence of the data file. ; ; ; Save the index values ; PUSH RDX PUSH R8 PUSH R9 PUSH R10 PUSH R11 PUSH R12 PUSH R13 PUSH R14 PUSH R15 ; ; ; SumsDifferent: IsDuplicate: ; ; Restore the index values ; POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP RDX ; ; Wheel cogs ; .IF R15 == UpperLimit MOV R15, 1 INC R14 .IF R14 == UpperLimit MOV R14, 1 INC R13 .IF R13 == UpperLimit MOV R13, 1 INC R12 .IF R12 == UpperLimit MOV R12, 1 INC R11 .IF R11 == UpperLimit MOV R11, 1 INC R10 .IF R10 == UpperLimit MOV R10, 1 INC R9 .IF R9 == UpperLimit MOV R9, 1 INC R8 .IF R8 == UpperLimit MOV R8, 1 INC RDX .ELSE INC R8 .ENDIF .ELSE INC R9 .ENDIF .ELSE INC R10 .ENDIF .ELSE INC R11 .ENDIF .ELSE INC R12 .ENDIF .ELSE INC R13 .ENDIF .ELSE INC R14 .ENDIF .ELSE INC R15 .ENDIF ; ; See if the Grinder is done ; .IF RDX == UpperLimit ; 1 .IF R8 == UpperLimit ; 2 .IF R9 == UpperLimit ; 3 .IF R10 == UpperLimit ; 4 .IF R11 == UpperLimit ; 5 .IF R12 == UpperLimit ; 6 .IF R13 == UpperLimit ; 7 .IF R14 == UpperLimit ; 8 .IF R15 == UpperLimit ; 9 INC CR0 ; All cells are at the designated Upper Limit .ENDIF ; 9 .ENDIF ; 8 .ENDIF ; 7 .ENDIF ; 6 .ENDIF ; 5 .ENDIF ; 4 .ENDIF ; 3 .ENDIF ; 2 .ENDIF ; 1 ; ; if it fails this test block, it means at least one of the cells has not yet hit the Upper Limit, so we iterate again ; .UNTIL CR0 != 0 ; ; need to wrap things up, and announce success or failure. ; END _Start