17.11.2016, 13:17
общий
это ответ
Здравствуйте, EccoVIP!
Вот программа, решающая следующую задачу:
для всех чисел Х из интервала 1:100000 находим частное от деления (Х+Х-1)/500
и проверяем его на простоту. Если простое, то считаем найденные числа.
Простота проверяется делением данного числа на все числа от 3 до [$8730$]Х.
Четные числа отбрасываются сразу проверкой младшего бита на 0
Одновременно ищется 200-е число Х, удовлетворяющее условию (Х+Х-1)/500 - простое
Вывод числа делается последовательным делением числа на 10, сохранением остатка в стеке
с последующим выводом символов-цифр в обратном порядке
[code lang=asm h=200]
.model small ;модель памяти
.386 ;будем использовать 32-битные регистры и команды сопроцессора
MINNUM equ 1 ;начинаем счет с 1
MAXNUM equ 100000 ;до 100000
DIVNUM equ 500 ;делим на 500
.stack 200h
.data
sNumbersCount db "Numbers count = $"
sNumber200 db "Number #200 = $"
sCountLess200 db "Numbers count < 200", 0dh, 0ah, '$'
temp dd ? ;здесь будет верхняя граница проверки на простое
number200 dd ? ;200-е число, удовлетворяющее условию
.code
start:
mov ax, @data ;настроим сегментный регистр данных на сегмент данных
mov ds, ax
call CalcSimples ;считаем простые числа
;выводим результат
lea dx, sNumbersCount ;поясняющая строка
mov eax, ebx ;количество чисел, удовлетворяющих условию
call PrintData ;выводим
cmp ebx, 200 ;сравним количество найденных чисел с 200
jb print_less_200 ;меньше - просто выводим сообщение
;выводим 200-е число
lea dx, sNumber200 ;поясняющая строка
mov eax, number200 ;само число
call PrintData ;выводим
jmp wait_key ;наожидание нажатия на клавишу
print_less_200: ;чисел меньше 200
lea dx, sCountLess200
mov ah, 9
int 21h
wait_key:
mov ah, 0 ;ждем нажатие на клавишу
int 16h
mov ax,4c00h ;завершаем программу
int 21h
CalcSimples proc ;поиск чисел
mov esi, DIVNUM ;делитель 500
xor ebx, ebx ;счетчик чисел
mov edi, MINNUM ;X, начинаем с MINNUM=1
mov ecx, MAXNUM ;счетчик цикла = MAXNUM=100000
simple_loop: ;цикл поиска
lea eax, [edi*2-1] ;eax = X+X-1
xor edx, edx ;подготавливаемся к делению
idiv esi ;edx:eax / esi
cmp eax, 2 ;рассматриваем частное от деления, отсеем числа меньшие 4
jb simple_next ;полученные числа, меньшие 2, игнорируем
je simple_found ;= 2 считаем простыми
cmp eax, 3
je simple_found ;= 3 также считаем простыми
;числа >= 4 анализируем на простоту
push edi ;сохраним текущее число edi=X (EDI используется в процедуре)
call simple ;проверяем на простоту, результат в флаге C, 1/0 - простое/непростое
pop edi
simple_add:
adc ebx, 0 ;добавляем флаг С к счетчику найденных чисел
cmp ebx, 200 ;найдем 200-е число
jne simple_next
mov number200, edi ;сохраним значение 200-го числа X, удовлетворяющее условию
simple_next:
inc edi ;следующее число Х
loop simple_loop ;на продолжение цикла
ret
simple_found: ;явное указание, что число простое
stc ;С=1
jmp simple_add ;на суммирование
CalcSimples endp
;анализ на простоту числа eax путем деления на все нечетные числа,
;начиная с 3, и заканчивая корню квадратному из числа
simple proc
test eax, 1 ;отсеем четные числа по младшему биту
je simple_no ;четные числа - непростые!
mov edi, eax ;сохраним число
;найдем максимальное число, до которого будем делить
;его найдем, как корень квадратный из нашего числа
mov temp, eax ;сохраним в памяти
fild temp ;загрузим в сопроцессор
fsqrt ;посчитаем корень
fistp temp ;и извлечем обратно в память, с округлением до ближайшего целого
mov ebp, 3 ;начальное значение делителя = 3
simple_cmp: ;цикла проверки на простоту
cmp ebp, temp ;проверим, прошли ли крайнее значение
jbe simple_continue ;нет - на продолжение проверки
stc ;да - прошли все, значит число простое
ret
simple_continue: ;анализируем на простоту делением и проверкой остатка на 0
mov eax, edi ;наше число
xor edx, edx ;подготавиваемся к делению
idiv ebp ;edx:eax / ebp
test edx, edx ;проверяем остаток на 0
jne simple_inc ;не ноль - на следующий делитель
simple_no:
clc ;разделилось нацело - число непростое!
ret
simple_inc:
add ebp, 2 ;следующий делитель
jmp simple_cmp ;на проверку выхода из анализа
simple endp
PrintData proc ;вывод сообщения
push eax ;сохраним выводимое число
mov ah, 9 ;выведем строку, адрес в dx
int 21h
pop eax ;наше число
;сформируем цифры числа в стеке
xor cx, cx ;счетчик цифр
mov esi, 10 ;будем делить на 10
digits_loop:
xor edx, edx ;готовимся к делению
div esi ;EDX:EAX / ESI
push dx ;сохраним остаток (очередную цифру) в стеке
inc cx ;считаем
test eax, eax ;есть еще?
jne digits_loop ;на продолжение
;выведем число
mov ah, 2 ;функция вывода символа из dl
print_loop:
pop dx ;извлекаем очередную цифру из стека (в обратном порядке)
or dl, '0' ;делаем из числа символ
int 21h ;выводим
loop print_loop ;по всем цифрам
mov dl, 0dh ;перейдем на новую строку
int 21h
mov dl, 0ah
int 21h
ret
PrintData endp
end start ;конец программы с точкой входа
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен