- Commit
- cdde6db78daac54b57f4db8cb2f389c5a2fa5139
- Parent
- f0b814c4e433cb097c83c1a7f80adf7aa74a3094
- Author
- Pablo Escobar Gaviria <gark.garcia@protonmail.com>
- Date
Cleaned the DOS x86 implementation.
An exercise on polyglossy: the same problem solved on multiple languages
Cleaned the DOS x86 implementation.
5 files changed, 198 insertions, 413 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Modified | .gitignore | 2 | 0 | 2 |
Modified | Elixir/digital_sum.ex | 5 | 5 | 0 |
Renamed | hla/conjecture.hla -> Extra/High Level Assembly/conjecture.hla | 0 | 0 | 0 |
Added | Extra/x86/PROGRAM.ASM | 193 | 193 | 0 |
Deleted | x86/PROGRAM.ASM | 411 | 0 | 411 |
diff --git a/.gitignore b/.gitignore @@ -4,9 +4,7 @@ *.IMG *.beam bin -bin/ build Statistics Latex -Q# Cuda
diff --git a/Elixir/digital_sum.ex b/Elixir/digital_sum.ex @@ -1,3 +1,8 @@ +# The following program is a simple test for the following conjecture: + +# Let S: N -> N be the sum of the digits of a positive integer. +# For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an integer. + defmodule Conjecture do def main max, n_processes do if max < 0 or n_processes <= 0 do
diff --git a/hla/conjecture.hla b/Extra/High Level Assembly/conjecture.hla
diff --git a/Extra/x86/PROGRAM.ASM b/Extra/x86/PROGRAM.ASM @@ -0,0 +1,193 @@ +.model tiny + +.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 + org 100h + +start: + mov ax, @data + 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 + + mov ax, max + mov bx, 2 + mul bx + mov bx, ax + + mov ax, 0 +cache_sums_loop: + push bx + push ax + call sum_digits + mov [si], bx + + pop ax + add si, 2 + inc ax + + pop bx + cmp ax, bx + jb cache_sums_loop + ret + +; Iterate `a` from 0 to `max` +counterexpl: + mov ax, a + call iter + + inc ax + mov a, ax + cmp ax, max + jbe counterexpl + + call ok + +; Iterate `b` from `a` to 0 +iter: + mov ax, a + mov b, ax + +iter_loop: + call test_pair + + dec b + mov ax, b + cmp ax, 0 + jae iter_loop + ret + +test_pair: + ; Calculate S(A + B) and store it in sumAB + mov si, offset sums_cache + add si, a + add si, b + mov ax, [si] + mov sumAB, ax + mov ax, si + + ; Calculate S(A) and store it in sumA + mov si, offset sums_cache + add si, a + mov ax, [si] + mov sumA, ax + + ; Calculate S(B) and store it in sumB + mov si, offset sums_cache + add si, b + mov ax, [si] + mov sumB, ax + + + ; 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 + div cx + + cmp dx, 0 + jne fail + + ret + +sum_digits: + mov cx, 10 ; Store the devident in cx + mov bx, 0 ; Clear the register where the result will be stored +sum_loop: + mov dx, 0 ; Clear the rest of the division + + div cx ; Divide ax by cx + add bx, dx ; Add the rest of the division ax/cx to bx + + ; Loop until ax equals 0 + cmp ax, 0 + ja sum_loop + ret + +;; Exit with exit-code 0 +ok: + mov al, 0 + call quit + ret + +;; Exit with exit-code 1 +fail: + mov al, 1 + call quit + ret + +;; Exit with exit-code 2 +invalid_input: + mov al, 2 + + call quit + ret + +;; Exit with exit-code `al` +quit: + mov ah, 4ch + int 21h + ret +end start
diff --git a/x86/PROGRAM.ASM b/x86/PROGRAM.ASM @@ -1,411 +0,0 @@ -.model tiny - -.stack 1000h - -.data - input db 8 DUP(0) - invalid db "' is not a natural number!", 0dh, 0ah, 0dh, 0ah, "$" - too_big db " is too big!", 0dh, 0ah, 0dh, 0ah, "$" - - max dw 0 - a dw 0 - b dw 0 - sumAB dw 0 - sumA dw 0 - sumB dw 0 - - sums_cache dw 25000 DUP(0) - - start_time dw 0 - end_time dw 0 - - proof db 0dh, 0ah, "The conjecture is proved for all natural numbers smaller or equals to $" - counter db 0dh, 0ah, "The conjecture is disproved! Here's a counterexample: ($" - loading db 0dh, 0ah, "LOADING. . .$" - loaded db 0dh, 0ah, "LOADED. . . in $" - - intro1 db 0dh, 0ah, "This program is a simple test for the following conjecture:", 0dh, 0ah, "$" - intro2 db 0dh, 0ah, "Let S: N -> N be the sum of the digits of a positive integer.", 0dh, 0ah, "$" - intro3 db "For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an integer.", 0dh, 0ah, "$" - intro4 db 0dh, 0ah, "What value would you like to test the conjecture for? $" - -.code - org 100h - -start: - mov ax, @data - mov ds, ax - - ; Print the intro messages to the screen - mov ah, 9h - mov dx, offset intro1 - int 21h - mov dx, offset intro2 - int 21h - mov dx, offset intro3 - int 21h - mov dx, offset intro4 - int 21h - - call read_uint ; Retrieve user input - - ; Set the start_time variable - mov si, offset start_time - call get_time - - mov ah, 9h - mov dx, offset loading - int 21h - - call cache_sums - call iter - -read_uint: - ; Load the user input into the input - mov ax, cs - mov ds, ax - mov input[0], 6 ; Configure the input length - mov dx, offset input - mov ah, 0ah - int 21h - - ; Print '\n' - mov ah, 2h - mov dx, 0dh - int 21h - mov dx, 0ah - int 21h - - ; Move si to the to adress of the first character in the input - mov si, offset input - add si, 2 - - mov ax, 0 ; Initialize the register where the result will be stored - mov cx, 1 ; Initialize a counter - -read_loop: - mov bx, 0 ; Clear bx - mov bl, [si] ; Read a character into bx - inc cx ; Increment the counter - inc si ; Increment the source index - - ; 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 bl, 30h - - ; ax = ax * 10 + bx - push cx - mov cx, 10 - mul cx - pop cx - add ax, bx - - cmp ax, 12500 - ja short input_too_big - - ; Jump if the counter is still smaller than the input length - cmp cl, input[1] - jbe short read_loop - - mov max, ax - ret - -invalid_input: - mov ah, 2h - - ; Print '\'' - mov dx, 27h - int 21 - - mov si, offset input - call print_buffer - - ; Print the rest of the message - mov ah, 9h - mov dx, offset invalid - int 21h - - call quit - ret - -input_too_big: - mov si, offset input - call print_buffer - - mov ah, 9h - mov dx, offset too_big - int 21h - - call quit - ret - -cache_sums: - mov si, offset sums_cache - - mov ax, max - mov bx, 2 - mul bx - mov bx, ax - - mov ax, 0 -cache_sums_loop: - push bx - push ax - call sum_digits - mov [si], bx - - pop ax - add si, 2 - inc ax - - pop bx - cmp ax, bx - jb short cache_sums_loop - ret - -; Prints the characters of a buffer referenced by si -print_buffer: - mov bh, si[1] - - add si, 2 - mov ch, 0 - - mov ah, 2h -print_buffer_loop: - mov dl, [si] - int 21h - - inc ch - inc si - - cmp ch, bh - jb short print_buffer_loop - ret - -; Iterate a from 0 to max -iter: - mov ax, a - call test_num - - inc ax - mov a, ax - cmp ax, max - jbe short iter - - call proved - -; Iterate b from a to max -test_num: - mov ax, a - mov b, ax - -test_loop: - call test_pair - - inc b - mov ax, b - cmp ax, max - jbe short test_loop - ret - -test_pair: - ; Calculate S(A + B) and store it in sumAB - mov si, offset sums_cache - add si, a - add si, b - mov ax, [si] - mov sumAB, ax - mov ax, si - - ; Calculate S(A) and store it in sumA - mov si, offset sums_cache - add si, a - mov ax, [si] - mov sumA, ax - - ; Calculate S(B) and store it in sumB - mov si, offset sums_cache - add si, b - mov ax, [si] - mov sumB, ax - - - ; 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 - div cx - - cmp dx, 0 - jne disproved - - ret - -sum_digits: - mov cx, 10 ; Store the devident in cx - mov bx, 0 ; Clear the register where the result will be stored -sum_loop: - mov dx, 0 ; Clear the rest of the division - - div cx ; Divide ax by cx - add bx, dx ; Add the rest of the division ax/cx to bx - - ; Loop until ax equals 0 - cmp ax, 0 - ja short sum_loop - ret - -proved: - call print_time - - mov ah, 9h - mov dx, offset proof - int 21h - - mov ax, max - call print_uint - - ; Print '!\n' - mov ah, 2h - mov dx, '!' - int 21h - mov dx, 0ah - int 21h - - call quit - ret - -disproved: - mov ah, 9h - mov dx, offset counter - int 21h - - mov ax, a - call print_uint - - ; Print ', ' - mov ah, 2h - mov dx, ',' - int 21h - mov dx, ' ' - int 21h - - mov ax, b - call print_uint - - ; Print ')\n' - mov ah, 2h - mov dx, ')' - int 21h - mov dx, 0ah - int 21h - - call quit - ret - -print_uint: - mov bx, 10 - mov cx, 0 - -print_uint_collect: - mov dx, 0 - div bx - add dx, 30h - - push dx - inc cx - - cmp ax, 0 - ja short print_uint_collect - - mov ah, 2h - -print_uint_loop: - pop dx - int 21h - dec cx - - cmp cx, 0 - ja short print_uint_loop - ret - -print_time: - ; Set the end_time variable - mov si, offset end_time - call get_time - - mov ah, 9h - mov dx, offset loaded - int 21h - - ; Print the elepsed time in milliseconds - mov ax, end_time - sub ax, start_time - mov cx, 10 - mul cx - call print_uint - - ; Print 'ms\n' - mov ah, 2h - mov dx, 'm' - int 21h - mov dx, 's' - int 21h - mov dx, 0ah - int 21h - ret - -; Gets the current minute in centiseconds and stores it in [si] -get_time: - ; Get system time - mov ah, 2ch - int 21h - - ; Add the minutes - mov ax, 0 - mov al, ch - mov bx, 6000 - mul bx - mov [si], ax - - ; Add the seconds - mov ax, 0 - mov al, dh - mov bx, 100 - mul bx - add [si], ax - - ; Add the centiseconds - mov ax, 0 - mov al, dl - add [si], ax - - ret - -; Print decimal value in ax, and a '.' to separate them. This was created for debugging porposes. -print_dot_dec: - push bx - push cx - push dx - push ax - call print_uint - mov dx, '.' - int 21h - pop ax - pop dx - pop cx - pop bx - ret - -quit: - mov ax, 4c00h - int 21h -end start