Реализация метода Ферма о делимости - Assembler
Формулировка задачи:
Необходима на языке assembler составить программу реализующую метод Ферма о делимости. Необходимо ввести 6ти значное число с клавиатуры, оно должно быть нечётным и не оканчиваться на "5".
Формулы:
N=(b^2)-(a^2)=(b-a)(b+a) b-a=1 b+a=N
Решение задачи: «Реализация метода Ферма о делимости»
textual
Листинг программы
.model tiny .486 .code org 100h start: mov ah,09h lea dx,buf11 int 21h mov ah,09h lea dx,qwerty int 21h entr: mov ah,09h ;Функция печати сообщения о просьбе ввести строку lea dx,buf12 ;Указываем начало адреса строковой переменной c сообщением int 21h ;Выполняем mov ah,0Ah ;Функция считывания нажатия клавиш lea dx,num11 ;Указываем смещение переменной num11 int 21h ;Выполняем xor ax,ax ;Обнуляем регистры xor bx,bx xor cx,cx xor dx,dx xor si,si xor di,di mov al,byte ptr[num11+2] cmp al,'-' je err mov cl,len_num11 mov di,cx prov: mov al,byte ptr[num11+1+di] cmp al,'9' jg err cmp al,'0' jl err dec di loop prov jmp contin err: mov ah,09h lea dx,errtxt int 21h mov byte ptr[num11+1],0 jmp entr contin: xor ax,ax xor bx,bx xor cx,cx xor dx,dx xor si,si xor di,di call numeric ;Получаем число в регистре EСX. Остальные регистры свободны finit mov var11,1 mov num12,ecx fild num12 fidiv var11 fiadd var11 fmul con11 fstp var11 m1: fild num12 fdiv var11 fadd var11 fmul con11 fld var11 fsub st(0),st(1) fabs fcomp eps fstsw ax sahf JC m2 fstp var11 JMP m1 m2: mov ah,09h lea dx,buf13 int 21h call OutFloat fcompp m3: fild num12 fld var11 fmul var11 fstp var12 fdiv var12 fadd var11 fadd var11 fmul con12 fld var11 fsub st(0),st(1) fabs fcomp eps fstsw ax sahf JC m4 fstp var11 JMP m3 m4: mov ah,09h lea dx,buf14 int 21h call OutFloat mov ah,0 int 16h mov ax,4ch int 21h buf11 db ' Kursovaya #30. Zadana celoe chislo. Naiti kvadrat i kub kornya iz etogo chisla.','$' buf12 db 10,13,' Enter number: ','$' num11 db 8,?,8 dup(?) len_num11=num11+1 num12 dd ? ;Переменная для хранения числа, преобразованнного из ASCII-строки num11 var11 dd ? var12 dd ? len_var11=var11 con11 dd 0.5 con12 dd 0.33333 eps dd 0.0005 buf13 db 10,13,' Square root from number: ','$' buf14 db 10,13,' Cubic root from number: ','$' errtxt db 10,13,' The entered number is lower from zero or been not the format. ',10,13,'$' qwerty db 10,13,' User enter whole number from 0 to infinity...','$' numeric proc near mov bx,1 mov di,10 mov cl,len_num11 mov si,cx xor ecx,ecx p11: cmp si,0 je p12 mov al,byte ptr [num11+si+1] sub al,30h mul ebx add ecx,eax mov eax,ebx mul edi mov ebx,eax xor eax,eax dec si jmp p11 p12: xor eax,eax xor ebx,ebx xor edx,edx ret numeric endp ; Вывод вещественного числа ; аргумент - количество цифр дробной части length_frac equ 5 ; локальные переменные ten equ word ptr [bp-2] temp equ word ptr [bp-4] OutFloat proc near enter 4, 0 ; пролог - выделим в кадре стека 4 байта под локальные переменные mov ten, 10 ftst ; определяем знак числа fstsw ax sahf jnc @positiv mov al, '-' ; если число отрицательное - выводим минус int 29h fchs ; и получаем модуль числа @positiv: fld1 ; загружаем единицу fld st(1) ; копируем число на вершину стека fprem ; выделим дробную часть fsub st(2), st ; отнимем ее от числа - получим целую часть fxch st(2) ; меняем местами целую и дробную части xor cx, cx ; обнуляем счетчик ; далее идет стандартный алгоритм вывода целого числа на экран @1: fidiv ten ; делим целую часть на десять fxch st(1) ; обменяем местами st и st(1) для команды fprem fld st(1) ; копируем результат на вершину стека fprem ; выделим дробную часть (цифру справа от целой части) fsub st(2), st ; получим целую часть fimul ten ; *10 fistp temp ; получаем очередную цифру push temp ; заталкиваем ее глубже в стек inc cx ; и увеличим счетчик fxch st(1) ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1) ftst ; проверим не получили ли в частном 0? fstsw ax sahf jnz @1 ; нет - продолжим цикл @2: ; извлекаем очередную цифру, переводим её в символ и выводим. pop ax add al, '0' int 29h loop @2 ; далее то же самое, только для дробной части. Алгоритм похож на вывод целого числа, только вместо деления умножение и проход по числу слева fstp st ; сначала проверим, есть ли дробная часть fxch st(1) ftst fstsw ax sahf jz @quit ; дробная часть отсутствует mov al, '.' int 29h ; если присутствует - выведем точку mov cx, length_frac ; помещаем в счетчик длину дробной части @3: fimul ten ; умножим на 10 fxch st(1) ; подготовка для fprem - меняем st и st(1) местами и fld st(1) ; копируем число на вершину fprem ; отделим дробную часть от целой fsub st(2), st ; и оставляем дробную fxch st(2) fistp temp ; выталкиваем полученное число из стека в temp mov ax, temp ; по дробной части идем слева, значит число выводим сразу, без предварительного сохранения в стек or al, 30h ; перевод в ascii int 29h ; на экран fxch st(1) ; подготовим стек к следующему шагу цикла (полученное частное на вершину, в st(1) - 1) ftst fstsw ax sahf ; проверим на 0 остаток дробной части loopne @3 @quit: ;fstp ; готово. Чистим стек сопроцессора fstp st leave ; эпилог ret 2 OutFloat endp end start