БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ
Кафедра программного обеспечения информационных технологий
Факультет ФКСиС
Специальность ПОИТ
Индивидуальная практическая работа № 2
по дисциплине «Языки программирования часть 1»
Вариант 5
Выполнил студент: Бордон Е.С.
группа 991051
Зачетная книжка № 99105004
Минск 2021
Условия задачи
Написать и отладить программу на языке Ассемблер.
Задан одномерный массив. Вывести на экран элементы массива,
кратные 5 и их количество. Массив задать в сегменте данных или ввести с
клавиатуры.
Пояснения к работе программы
Программы написаны на Assembler для MASM для выполнения на современных 32-битных процессорах в ОС Windows с использованием среды разработки SASM и отладчика OllyDbg.
Программа содержит предопределённый в сегменте данных массив четырёхбайтных чисел. При необходимости можно перекомпилировать программу с другим массивом данных.
Результат работы программы
Рис 1. Результат работы программы
Тестовый набор данных:
Массив данных |
Числа кратные 5 |
Число кратных чисел |
2,5,11,8,15 |
5,15 |
2 |
1,3,5,7,9,11,15,20 |
5,15,20 |
3 |
500,501,499,6005 |
500,6005 |
2 |
5,5,5,5,5,5,5,5 |
5,5,5,5,5,5,5,5 |
8 |
7,7,7,7,7,7,7,7 |
7,7,7,7,7,7,7,7 |
0 |
Листинг программы
.386 ; код скомпилируется для сравнительно современных 32-битных процессоров
.model flat, stdcall ; устанавливаем модель памяти windows, очистку стека осуществляет вызываемая подпрограмма
option casemap : none ; делаем переменные регистрозависимыми
include \masm32\include\kernel32.inc ; для использования базового API Windows
include \masm32\include\msvcrt.inc ; для использования crt_printf и crt_scanf (ввод/вывод с поддержкой формата)
includelib \masm32\lib\kernel32.lib ; для использования базового API Windows
includelib \masm32\lib\msvcrt.lib ; для использования crt_printf и crt_scanf (ввод/вывод с поддержкой формата)
CRLF equ 13, 10 ; синоним перевода строки в консоли
ELSIZE equ 4
.data
R dd n-1 ; длина прохода - количество неотсортированных элементов минус один
;*****************
array dd 2,5,11,8,15 ; задаём массив 4-байтных чисел
;*****************
n = ($ - array) / ELSIZE ; вычисляем длину массива, как текущая метки минус метка начала массива, разделенная на длину элемента - 4 байта
formatInt db '%d',0 ; описание формата целого числа
formatStr db '%s',0 ; описание формата строки
msgInitial db "Source array is:", CRLF, 0 ; вступление к выводу исходного массива
msgSorted db "Multiple of 5:", CRLF, 0 ; вступление к выводу чисел кратных 5
msgCount db "Total multiples of 5: ", CRLF, 0 ; вступление к выводу чисел кратных 5
msgFinal db "Enter any char and press 'Enter' for exit", CRLF, 0; инструкция по выходу из программы
msgCRLF db CRLF ; перенос строки
.code
start:
invoke crt_printf, ADDR formatStr, ADDR msgInitial ; выводим сообщение о выводе исходного массива
call printArr ; выводим исходный массив и инициализируем esi адресом начала массива
invoke crt_printf, ADDR formatStr, ADDR msgSorted ; выводим сообщение о выводе исходного массива
call printArrr ; выводим результат сортировки
invoke crt_printf, ADDR formatStr, ADDR msgCount ; выводим сообщение о числе кратных чисел
invoke crt_printf, ADDR formatInt, edi ; выводим результат
invoke crt_printf, ADDR formatStr, ADDR msgCRLF ; выводим перенос строки;
invoke crt_printf, ADDR formatStr, ADDR msgFinal ; объясняем, как выйти из программы
invoke crt_scanf, ADDR formatStr, ADDR formatStr ; переиспользуем переменную для хранения ненужных данных
invoke ExitProcess, 0 ; закрываем программу, возвращаемся к ОС
;_____________________________________________________________________________________
printArr proc ; вспомогательная процедура для вывода текущего состояния массива
mov ecx, n ; сохраняем количество элементов для счётчика цикла
mov esi, offset array ; сохраняем адрес начала массива в esi
xor edx, edx ; обнуляем счётчик элементов массива
lp1:
mov ebx, [esi + edx * ELSIZE] ; выбираем текущий элемент массива
push ecx ; сохраняем значение ecx в стек
push edx ; сохраняем значение edx в стек
invoke crt_printf, ADDR formatInt, ebx ; выводим результат
invoke crt_printf, ADDR formatStr, ADDR msgCRLF ; выводим перенос строки
pop edx ; восстанавливаем значение edx из стека
inc edx ; увеличиваем номер для корректного выбора следующего элемента
pop ecx ; восстанавливаем значение ecx из стека
loop lp1 ; привязываем цикл к метке lp1
ret ; возвращаемся в вызвавшую программу
printArr endp ; конец вспомогательной процедуры
;______________________________________________________________________________
;вывод только кратных 5 чисел
;_____________________________________________________________________________________
printArrr proc ; вспомогательная процедура для вывода текущего состояния массива
mov ecx, n ; сохраняем количество элементов для счётчика цикла
mov esi, offset array ; сохраняем адрес начала массива в esi
xor edx, edx ; обнуляем счётчик элементов массива
xor edi, edi ; счетчик числа кратных чисел
;(dx,ax)/bx = ax, dx **** a/b ****
lp1:
mov ebx, [esi + edx * ELSIZE] ; выбираем текущий элемент массива
push ecx ; сохраняем значение ecx в стек
push edx ; сохраняем значение edx в стек
xor edx, edx ; очищаем остаток от деления
mov eax, ebx ; помещаем наше числа в eax
mov ecx, ebx ; ecx наше число
mov ebx, 5 ; наш делитель
div ebx ;(dx,ax)/bx = ax, dx
cmp edx, 0 ; делаем проверку остатка от деления
jl incorrect ; <
jg incorrect ; >
jz correct ; =
correct: ; если число кратно 5
inc edi
mov ebx, ecx
invoke crt_printf, ADDR formatInt, ebx ; выводим результат
invoke crt_printf, ADDR formatStr, ADDR msgCRLF ; выводим перенос строки
JMP exit
incorrect: ; если число не кратно 5
mov ebx, ecx
JMP exit
exit:
pop edx ; восстанавливаем значение edx из стека
inc edx ; увеличиваем номер для корректного выбора следующего элемента
pop ecx ; восстанавливаем значение ecx из стека
loop lp1 ; привязываем цикл к метке lp1
ret ; возвращаемся в вызвавшую программу
printArrr endp ; конец вспомогательной процедуры
;______________________________________________________________________________
end start ; программа начнёт выполнение с метки start