Консультация № 190021
13.11.2016, 18:34
0.00 руб.
0 8 1
Здравствуйте! Прошу помощи в следующем вопросе:
Как можно проще и быстрее, пожалуйста, помогите... с комментариями , пожалуйста, не понятно...
Тема
Использование операторов сравнения (cmp), условных(Jxx), безусловных (JMP) переходов и
циклов (LOOOP).


Задание из двух частей. В первом задании необходимо подсчитать количество
чисел, соответствующих определенному условию на некотором числовом промежутке.
Во втором задании требуется модифицировать свою программу так, чтобы найти и
вывести на экран двухсотое число или пару чисел соответствующих заданному
условию. Если таких чисел меньше двухсот, то вывести об этом сообщение на экран.
[b] На промежутке от 1 до 100 000
Подсчитать количество таких чисел X, что (Х+Х-1)div500 - простое число
Ответ вывести на экран
[/b]

Обсуждение

давно
Посетитель
7438
7205
14.11.2016, 11:55
общий
Адресаты:
Используем 16-битные регистры или 32-битные?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
400150
26
15.11.2016, 17:46
общий
любые...
давно
Посетитель
7438
7205
15.11.2016, 18:37
общий
Адресаты:
(Х+Х-1)div500, как это понимать?
Х+Х-1 - число нечетное
После деления на 500 получаем частное и остаток. Остаток будет всегда (число нечетное).
Остаток отбрасываем, рассматриваем только частное. Так получается?
Но тогда придется рассматривать порядка 250 одинаковых чисел... Как-то непонятно зачем...

Да и вот это "двухсотое число или пару чисел соответствующих заданному условию" не совсем понятно.
Какая такая пара чисел имеется в виду?

Разъясните условие, как Вы его понимаете
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
400150
26
15.11.2016, 21:40
общий
Цитата: Лысков Игорь Витальевич
дело в том , что я сам и не понял, там такая неопределенность с заданием этим, елси можете помочь, помогите, пожалуйста по свой идеи....
давно
Посетитель
400150
26
15.11.2016, 21:42
общий
Исходные данные
Как работать с циклами описано в руководстве:
Index.html
в главе 3 в разделе циклы и условные переходы.
Метки необходимо объявлять так, как это делается в языке pascal.
Прикрепленные файлы:
45ce4ed8ee2f42b3d2f334d1793de41e.rar
давно
Посетитель
7438
7205
15.11.2016, 23:21
общий
Адресаты:
Как работать с циклами и условными переходами, я знаю и так
Ладушки, завтра что-нибудь нарисую
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
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]
5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
400150
26
17.11.2016, 15:18
общий
Цитата: Лысков Игорь Витальевич
спасибо!
Форма ответа