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