section .bss
X resd 12 ; числители
Y resd 12 ; знаменатели
N resd 1
sum_temp resd 1
num_res resd 1
den_res resd 1
section .text
global main
extern io_get_dec, io_print_dec, io_print_char
main:
; Ввод количества дробей N (1..12)
call io_get_dec
mov [N], eax
cmp eax, 1
jl finish
cmp eax, 12
jg finish
xor ecx, ecx
input_loop:
cmp ecx, [N]
jge compute_lcm
call io_get_dec
mov [X + ecx*4], eax
call io_get_dec
cmp eax, 0
je finish ; запрещаем нулевой знаменатель
mov [Y + ecx*4], eax
inc ecx
jmp input_loop
;--------------------------------
; Вычисляем общий знаменатель через LCM
compute_lcm:
mov esi, 1 ; общий знаменатель
xor ecx, ecx
lcm_loop:
cmp ecx, [N]
jge sum_fraction
mov eax, esi
mov ebx, [Y + ecx*4]
call lcm_64bit ; используем безопасный LCM
mov esi, eax
inc ecx
jmp lcm_loop
;--------------------------------
; Вычисляем сумму дробей S
sum_fraction:
xor eax, eax
mov [sum_temp], eax
xor ecx, ecx
sum_loop:
cmp ecx, [N]
jge simplify_fraction
mov eax, esi
mov ebx, [Y + ecx*4]
xor edx, edx
div ebx ; общий / Yi
mov ebx, eax
mov eax, [X + ecx*4]
imul eax, ebx
xor edx, edx ; безопасно перед add
add eax, [sum_temp]
mov [sum_temp], eax
inc ecx
jmp sum_loop
;--------------------------------
; Упрощение дроби
simplify_fraction:
mov eax, [sum_temp]
mov ebx, esi
call gcd
mov ecx, eax
mov eax, [sum_temp]
xor edx, edx
div ecx ; числитель / gcd
mov [num_res], eax
mov eax, esi
xor edx, edx
div ecx ; знаменатель / gcd
mov [den_res], eax
mov eax, [num_res]
call io_print_dec
mov eax, '/'
call io_print_char
mov eax, [den_res]
call io_print_dec
finish:
ret
;--------------------------------
; GCD(a,b) через алгоритм Евклида
gcd:
cmp ebx, 0
je gcd_done
gcd_loop:
xor edx, edx
div ebx
mov eax, ebx
mov ebx, edx
cmp ebx, 0
jne gcd_loop
gcd_done:
ret
;--------------------------------
; Безопасный LCM с 64-битным умножением
; Вход: eax = a, ebx = b
; Выход: eax = lcm(a,b)
lcm_64bit:
push eax
push ebx
call gcd
mov ecx, eax ; сохранить gcd
pop ebx ; восстановить b
pop eax ; восстановить a
xor edx, edx
mul ebx ; 64-битное умножение: edx:eax = a*b
; делим 64-битное число edx:eax на ecx
mov ebx, ecx
div ebx ; eax = (a*b)/gcd
ret