a-conjecture-of-mine

An exercise on polyglossy: the same problem solved on multiple languages

commit 67fa9141d6d16cf6121dbaa5823700b3a89c8d9b
parent cdde6db78daac54b57f4db8cb2f389c5a2fa5139
Author: Pablo Escobar Gaviria <gark.garcia@protonmail.com>
Date:   Sun, 29 Dec 2019 17:11:55 -0200

Optimized the x86 implementation, deprecating the unnecessary use of static variables in the program.

Diffstat:
MExtra/x86/PROGRAM.ASM | 194++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 98 insertions(+), 96 deletions(-)
diff --git a/Extra/x86/PROGRAM.ASM b/Extra/x86/PROGRAM.ASM
@@ -3,13 +3,6 @@
 .stack 1000h
 
 .data
-        max        dw 0
-        a          dw 0
-        b          dw 0
-        sumAB      dw 0
-        sumA       dw 0
-        sumB       dw 0
-
         sums_cache dw 25000 DUP(0)
 
 .code
@@ -20,139 +13,103 @@ start:
         mov  ds, ax
 
         call read_uint ; Retrieve user input  
-
         call cache_sums
         call counterexpl
 
-read_uint:
-        push si
-
-        ; Move the start of the command-line tail to `si`
-        mov  si, ds
-        add  si, 81h
-
-read_loop:
-        ; Read a character from the command-line tail
-        mov  bx, [si]
-
-        ; Jump out of the loop at the end of the first arg
-        cmp  bx, 20h
-        jmp  read_end
-        cmp  bx, 0dh
-        jmp  read_end
-
-        ; Check if it's a numeric character
-        cmp  bx, 30h
-        jb   invalid_input
-        cmp  bx, 39h
-        ja   invalid_input
-
-        ; Convert the character code into a decimal digit
-        sub  bx, 30h
-
-        ; ax = ax * 10 + bx
-        push cx
-        mov  cx, 10
-        mul  cx
-        pop  cx
-        add  ax, bx
-
-        ; Increment the pointer to the argument string and keep looping
-        inc  si
-        jmp  read_loop
-
-read_end:
-        mov  max, ax
-        pop  si
-        ret
-
 cache_sums:
-        mov  si, offset sums_cache
+        push ax                 ; Preserve the value of max
 
-        mov  ax, max
-        mov  bx, 2
-        mul  bx
-        mov  bx, ax
+        mov  si, offset sums_cache
 
-        mov  ax, 0
+        mov  cx, 2
+        mul  cx                 ; ax = max * 2
 cache_sums_loop:
-        push  bx
-        push  ax
-        call  sum_digits
-        mov   [si], bx
+        call sum_digits
+        mov  [si], bx
 
-        pop  ax
         add  si, 2
-        inc  ax
+        dec  ax
 
-        pop  bx
-        cmp  ax, bx
-        jb   cache_sums_loop
+        cmp  ax, 0
+        ja   cache_sums_loop    ; while ax > 0, keep looping
+
+        pop  ax                 ; Restore the value of max to ax 
         ret
 
 ; Iterate `a` from 0 to `max`
+; At the start of this routine ax holds the value of max
 counterexpl:
-        mov  ax, a
+        mov  cx, 9              ; Set the devident to 9
+counterexpl_loop:
         call iter
 
-        inc  ax
-        mov  a, ax
-        cmp  ax, max
-        jbe  counterexpl
+        dec  ax                 ; a -= 1
+        cmp  ax, 0              ; if a > 0, keep looping
+        ja   counterexpl_loop
 
         call ok
+        ret
 
 ; Iterate `b` from `a` to 0
+; At the start of this routine ax holds the value of a
 iter:
-        mov  ax, a
-        mov  b, ax
-
+        mov  bx, ax
 iter_loop:
         call test_pair
 
-        dec  b
-        mov  ax, b
-        cmp  ax, 0
+        dec  bx
+        cmp  bx, 0
         jae  iter_loop
         ret
 
+; At the start of this routine ax holds the value of a
+; and bx holds the value of b
 test_pair:
-        ; Calculate S(A + B) and store it in sumAB
+        ; Preserve bp and sp
+        push bp
+        mov  bp, sp
+
+        sub  sp, 6              ; Make room for 3 words [S(a +  b), S(a) and S(b)]
+        push ax                 ; Preserve the value of a
+
+        ; S(a + b) = sums_cache[a + b]
         mov  si, offset sums_cache
-        add  si, a
-        add  si, b
+        add  si, ax
+        add  si, bx
         mov  ax, [si]
-        mov  sumAB, ax
-        mov  ax, si
+        mov  [bp - 6], ax
 
-        ; Calculate S(A) and store it in sumA
-        mov  si, offset sums_cache
-        add  si, a
+        ; S(a) = sums_cache[a]
+        sub  si, bx
         mov  ax, [si]
-        mov  sumA, ax
+        mov  [bp - 4], ax
 
-        ; Calculate S(B) and store it in sumB
+        ; S(b) = sums_cache[b]
         mov  si, offset sums_cache
-        add  si, b
+        add  si, bx
         mov  ax, [si]
-        mov  sumB, ax 
+        mov  [bp - 2], ax
 
+        ; Store S(a + b) - S(a) - S(b) in ax
+        mov  ax, [bp - 6]
+        sub  ax, [bp - 4]
+        sub  ax, [bp - 2]
 
-        ; Calculate S(a + b) - S(a) - S(b) in ax
-        mov  ax, sumAB
-        sub  ax, sumA
-        sub  ax, sumB
-
-        mov  cx, 9 ; Set the devident to 9
-        mov  dx, 0 ; Clear the register where the rest will be stored
+        mov  dx, 0              ; Clear the register where the rest will be stored
         div  cx
+        pop  ax                 ; Restore the value of a to ax
 
-        cmp  dx, 0
+        cmp  dx, 0              ; if (S(a + b) - S(a) - S(b)) % 9 != 0, goto fail
         jne  fail
 
+        ; Restore bp and sp
+        mov  sp, bp
+        pop  bp
         ret
 
 sum_digits:
+        push ax
+
         mov  cx, 10 ; Store the devident in cx
         mov  bx, 0 ; Clear the register where the result will be stored
 sum_loop:
@@ -164,6 +121,51 @@ sum_loop:
         ; Loop until ax equals 0
         cmp  ax, 0
         ja   sum_loop
+
+        pop  ax
+        ret
+
+; Reads the first element of the command-line tail and
+; tries to convert it to an unsigned word
+read_uint:
+        mov  ax, 0
+        mov  cx, 10
+        push si
+
+        ; Move the start of the command-line tail to `si`
+        ;mov  si, ds
+        mov  si, 5eh
+
+read_loop:
+        ; Read a character from the command-line tail
+        mov  bh, 0
+        mov  bl, [si]
+
+        ; Jump out of the loop at the end of the first arg
+        cmp  bl, ' '
+        jmp  read_uint_end
+        cmp  bl, 0dh
+        jmp  read_uint_end
+
+        ; Check if it's a numeric character
+        cmp  bl, 30h
+        jb   short invalid_input
+        cmp  bl, 39h
+        ja   short invalid_input
+
+        ; Convert the character code into a decimal digit
+        sub  bx, 30h
+
+        ; ax = ax * 10 + bx
+        mul  cx
+        add  ax, bx
+
+        ; Increment the pointer to the argument string and keep looping
+        inc  si
+        jmp  read_loop
+
+read_uint_end:
+        pop  si
         ret
 
 ;; Exit with exit-code 0