Реализация метода Ферма о делимости - 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

Оцени полезность:

7   голосов , оценка 4 из 5