Содержание
1 Постановка задачи…………………………
2 Разработка программы без интерфейса………………
2.1 Спецификация задачи…………………………
2.2 Организация данных…………………………
2.3 Разработка алгоритмов………………
2.4 Текст программы…………………
3 Разработка программы с интерфейсом..………
3.1 Спецификация задачи…………………………
3.2 Организация данных…………………………
3.3 Разработка алгоритмов………………
3.4 Текст программы…………………
Заключение………………
Список использованных источников………………
1 Постановка задачи
Написать макрокоманду для выборки из некоторого массива слов со знаком всех элементов больших одного значения, но меньших другого. С помощью этой макрокоманды обработать два массива, выбирая из 1-го элементы большие 1000, но меньшие 2000, а из 2-го – большие (–5000), но меньшие 50000.
2 Разработка программы без интерфейса
2.1 Спецификация задачи
Программа должна выполнять обработку двух массивов слов со знаком, которые заданы в памяти. Макрокоманде передаются два массива, количество элементов массива и интервал для выборки элементов из массива. Макрокоманда сравнивает каждый элемент с максимальной и минимальной границей интервала. Если элемент, находится в пределах интервала, то элемент записывается в выходной массив
2.2 Организация данных
Для хранения исходных данных и результатов используются массивы:
ArrS1 dw 07CF EC77, EC79, 0000, 1387, 1389, 03E8, 05DC, 07D2, F830
Counter1 = ($ — offset ArrS1) / type ArrS1
ArrD1 dw ?, Counter1 dup (?) ;первый выходной массив
;второй выходной массив
ArrS1 dw 07CF, 03E9, 03E7, 07D1, FF9C, 05DC, 07DO
Counter2 = ($ — offset ArrS2) / type ArrS2
ArrD2 dw ?, counter2 dup (?) ;второй выходной массив
В задаче также были введены следующие вспомогательные константы для хранения границ интервалов
min1 = 1000 ;промежуток от 1000 до 2000
max1 = 2000
min2 = — 5000 ;промежуток от -5000 до 5000
max2 = 5000
Для передачи параметров в макрокоманду используются переменные:
x — входной массив
у — выходной массив
counter — количество чисел в массиве
min, max — промежуток для выборки,
2.3 Разработка алгоритмов
Алгоритм макроуровня представлен на рисунке 2.3.1.
Рисунок 2.3.1 – Алгоритм макроуровня
Алгоритм подпрограммы представлен на рисунке 2.3.2.
Рисунок 2.3.2 – Алгоритм макрокоманды
2.4 Текст программы
Name program ;Имя программы
min1 = 1000 ;промежуток от 1000 до 2000
max1 = 2000
min2 = -5000 ;промежуток от -5000 до 5000
max2 = 5000
Data Segment ;сегмент данных
ArrS1 dw 07CF EC77, EC79, 0000, 1387, 1389, 03E8, 05DC, 07D2, F830
;вычисление длины массива
Counter1 = ($ — offset ArrS1) / type ArrS1
ArrD1 dw ?, Counter1 dup (?) ;первый выходной массив
;второй выходной массив
ArrS1 dw 07CF, 03E9, 03E7, 07D1, FF9C, 05DC, 07DO
Counter2 = ($ — offset ArrS2) / type ArrS2
ArrD2 dw ?, counter2 dup (?) ;второй выходной массив
Data EndS
Code Segment ;сегмент кода
Assume CS:Code, DS:Data
;ArrS — входной массив
;ArrD — выходной массив
;counter — количество чисел в массиве
;min, max — промежуток для выборки,
abc Macro ArrS, ArrD, counter, min, max
LOCAL M1, M2 ;локализация меток
LEA SI, ArrS ;загрузка начальных
LEA DI, ArrD ;адресов
MOV CX, COUNTER ;загрузка счетчика циклов
ADD DI, type ArrS ;модификация адреса
XOR DX,DX ;обнуление счетчика выбранных элементов
M2: MOV AX, [SI] ;загрузка элемента
CMP AX, min ;сравнение с нижним интервалом
JLE M1 ;если число меньше, то переход по метке
CMP AX, max ;сравнение с верхним интервалом
JGE M1 ;если число больше, то переход по метке
MOV [DI], AX ;выбор элемента
INC DX ;инкремент выбранных элементов
ADD DI, type ArrD ;модификация адреса входного массива
M1: ADD SI, type ArrS ;модификация адреса входного массива
LOOP M2 ;зацикливание
MOV ArrD, DX ;запись элементов в выходной массив
endm
; Основная программа
Start:
MOV AX, Data ;инициализация сегментного регистра
MOV DS, AX
abc ArrS1, ArrD1, Counter1, min1, max1 ;макровызов
abc ArrS2, ArrD2, Counter2, min2, max2 ;макровызов
Code EndS
End Start
3 Разработка программы с интерфейсом
3.1 Спецификация задачи
Программа должна выполнять обработку двух массивов слов со знаком, которые вводятся вручную с клавиатуры. Количество элементов массивов также вводятся с клавиатуры.
3.2 Организация данных
Для хранения исходных данных и результатов используются массивы:
IN_ARR1 DW 256 DUP (?) ;входные массивы
IN_ARR2 DW 256 DUP (?)
OUT_ARR1 DW 256 DUP (?) ;выходные массивы
OUT_ARR2 DW 256 DUP (?)
В задаче также были введены следующие вспомогательные переменные и константы:
STR_BUFF DB 255,?,255 DUP (?) ;буфер ввода
COUNTER DW ? ;счетчики
COUNTERX1 DW ?
MINUS DB ? флаг минуса
FERR DB ? ;флаг ошибки
Для вывода на экран были введены строковые константы:
MSG_ARR1 DB ‘FIRST ARRAY ‘,10,13,’$’
MSG_ARR2 DB ‘SECOND ARRAY ‘,10,13,’$’
MSG_NOT_ITEM DB ‘NOT ITEM ‘,10,13,’$’
MSG_INP_ARR1 DB ‘ENTER NUMBERS F
MSG_INP_ARR2 DB ENTER NUMBERS SE
MSG_COUNT DB ‘ARRAY COUNT (1…255) :’,’$’
MSG_X1 DB ‘X1[ ‘,’$’
MSG_X2 DB ‘X2[ ‘,’$’
MSG_Y1 DB ‘Y1[ ‘,’$’
MSG_Y2 DB ‘Y2[ ‘,’$’
MSG_IND DB ‘]=’,’$’
3.3 Разработка алгоритмов
Алгоритм макроуровня представлен на рисунке 3.3.1.
Рисунок 3.3.1 – Блок-схема алгоритма макроуровня
Алгоритм ввода и записи данных в память представлен на рисунке 3.3.2.
Рисунок 3.3.2 – Блок-схема алгоритмов ввода и записи данных в память
Алгоритм подпрограммы вывода на экран выходного массива представлен на рисунке 3.3.3.
Рисунок 3.3.3 – Блок-схема алгоритма вывода выходного массива
Алгоритм подпрограммы ввода количества элементов массива представлен на рисунке 3.3.4.
Алгоритм подпрограммы перевода введенной строки в число, для записи в массив, представлен на рисунке 3.3.5.
Алгоритм подпрограммы перевода числа в строку, для вывода на экран, представлен на рисунке 3.3.6.
3.4 Текст программы
Name Program2
MIN1 = 1000 ;интервал выборки от 1000 до 2000
MAX1 = 2000
MIN2 = — 5000 ;интервал выборки от -5000 до 5000
MAX2 = 5000
;Описание переменных
DATA SEGMENT
MSG_ARR1 DB 10,13,’FIRST ARRAY ‘,’$’
MSG_ARR2 DB 10,13,’SECOND ARRAY ‘,’$’
MSG_NOT_ITEM DB ‘NOT ITEM ‘,10,13,’$’
MSG_INP_ARR1 DB 10,13,’ENTER NUMBERS FIRST:’,10,13,’$
MSG_INP_ARR2 DB 10,13,’ENTER NUMBERS 2-ND ‘,10,13,’$’
MSG_COUNT DB ‘ARRAY COUNT (0…255) :’,’$’
MSG_X1 DB ‘X1[ ‘,’$’
MSG_X2 DB ‘X2[ ‘,’$’
MSG_Y1 DB ‘Y1[ ‘,’$’
MSG_Y2 DB ‘Y2[ ‘,’$’
MSG_IND DB ‘ ] = ‘,’$’
MSG_EXT DB ‘PRESS ANY KEY TO EXIT !’,’$’
MSG_ERR DB 10,13,’INPUT ERROR’,10,13,’$’
MSG_CARR DB 10,13,’$’
IN_ARR1 DW 256 DUP (?)
IN_ARR2 DW 256 DUP (?)
OUT_ARR1 DW 256 DUP (?)
OUT_ARR2 DW 256 DUP (?)
STR_BUFF DB 255,?,255 DUP (?)
COUNTER DW ?
COUNTERX1 DW ? ;счетчик для X1
COUNTERX2 DW ? ;счетчик для X2
MINUS DW ? ;флаг минуса
FERR DB ? ;флаг ошибки
DATA ENDS
STACK SEGMENT
dw 16 dup (0)
StkTop Label word
STACK ENDS
CODE SEGMENT
ASSUME CS: CODE, DS: DATA
;X -ВХОДНОЙ МАССИВ
;Y -ВЫХОДНОЙ МАССИВ
;N- СЧЕТЧИК ЗАПИЧАННЫХ ЧИСЕЛ
;MIN, MAX — ИНТЕРВАЛ ДЛЯ ВЫБОРКИ
;ВЫХОД: N-число чисел соответствующих условию
CHOICE MACRO X, Y, N, MIN, MAX
LOCAL M1, M2 ,EXTM
LEA SI, X ;загрузка начального адреса входного массива
MOV CX, [N] ;загрузка счетчика цикла
MOV N, 0 ;обнуление счетчика
LEA DI, Y ;загрузка начального адреса выходного массива
M2:
CMP CX, 0
JE EXTM
MOV AX, [SI] ;чтение элемента
CMP AX, MIN ;сравниваем с минимальной границей
JLE M1 ;если меньше то идем на М1
CMP AX, MAX ;сравниваем с максимальной границей
JGE M1 ;если больше идем на M1
MOV [DI], AX ;загрузка выбранного числа в выходной массив
INC N ;увеличить счетчик записанных чисел
ADD DI, TYPE Y ;модификация адреса выходного массива
M1:
ADD SI, TYPE X ;модификация адреса
LOOP M2 ;зацикливание
EXTM:
ENDM
; Основная программа
START:
MOV AX, DATA ;инициализация
MOV DS, AX ;сегментного регистров
;ввод 1 массива
LEA DX, MSG_ARR1
CALL PRINT_MSG
CALL INP_COUNTER
MOV [COUNTERX1], AX ;поместить кол-во чисел в счетчик
CMP AX, 0 ;сравнить число с «0»
JE NEXT_ARRAY ;если введено «0» , переход
LEA DX, MSG_INP_ARR1 ;загрузка адреса сообщения
CALL PRINT_MSG ; приглашение к вводу в массив 1
LEA DI, IN_ARR1 ;загрузить адрес массива в DI
MOV CX, COUNTERX1 ;в CX поместить число элементов
LEA DX, MSG_X1 ;загрузить адрес сообщения
CALL INP_ARRAY ;вызвать процедуру ввода в массив
;ввод 2 массива
NEXT_ARRAY:
LEA DX, MSG_ARR2
CALL PRINT_MSG
CALL INP_COUNTER ;ввода числа элементов для ввода
MOV [COUNTERX2], AX ;поместить в переменную
CMP AX, 0 ;сравнить число с «0»
JE SEARCH ;пропустить ввод если введено 0
LEA DX, MSG_INP_ARR2 ;загрузка адреса сообщения
CALL PRINT_MSG ;вывести приглашение к вводу в 1
LEA DI, IN_ARR2 ;загрузить адрес массива в DI
MOV CX, COUNTERX2 ;в CX поместить число элементов
LEA DX, MSG_X2 ;загрузить адрес сообщения
CALL INP_ARRAY ;вызвать процедуру ввода в массив
;поиск чисел во входном массиве в заданных интервалах и запись в выходной массив
SEARCH:
;вызов макрокоманды поиска чисел в заданных интервалах
CHOICE IN_ARR1, OUT_ARR1, COUNTERX1, MIN1, MAX1
CHOICE IN_ARR2, OUT_ARR2, COUNTERX2, MIN2, MAX2
;вывод выходного массива 1
LEA DX, MSG_ARR1 ;вывести сообщение
CALL PRINT_MSG
LEA DX, MSG_CARR ;вывести сообщение
CALL PRINT_MSG
LEA DX, MSG_Y1 ;загрузка адреса вывода сообщения
MOV CX, [COUNTERX1] ;число записанных чисел в выходном массиве
LEA SI, OUT_ARR1 ;адрес выходного массива
CALL OUT_ARRAY
;вывод выходного массива 2
LEA DX, MSG_ARR2 ;вывести сообщение
CALL PRINT_MSG
LEA DX, MSG_CARR ;вывести сообщение
CALL PRINT_MSG
LEA DX, MSG_Y2 ;загрузка адреса вывода сообщения
MOV CX, [COUNTERX2] ;число записанных чисел в выходном массиве
LEA SI, OUT_ARR2 ;адрес выходного массива
CALL OUT_ARRAY
EXIT:
LEA DX, MSG_EXT
CALL PRINT_MSG ;сообщение о выходе
MOV AH, 0h
INT 016h ;ожидать нажатие клавиши
MOV AX, 4C00h
INT 021h ;выход из программы
; Подпрограмма для вывода сообщений
PRINT_MSG PROC
MOV AH, 09H
INT 21H
RET
PRINT_MSG ENDP
; Подпрограмма для ввода строки
INPUT_STR PROC
MOV AH, 0Ah ;функция ввода строки в буфер
INT 21H
RET
INPUT_STR ENDP
; Подпрограмма для ввода ошибки ввода
PRINT_ERROR PROC
LEA DX, MSG_ERR ;загрузить адрес сообщения
CALL PRINT_MSG ;вывести сообщение о ошибке
RET
PRINT_ERROR ENDP
; Подпрограмма для вывода строки отсутствия элементов
PRINT_ITEM PROC
LEA DX, MSG_NOT_ITEM ;загрузить адрес сообщения ошибкеи CALL PRINT_MSG ;вывести сообщение о ошибке
RET
PRINT_ITEM ENDP
;Процедура ввода числа элементов в массиве
;ВЫХОД: AX — число
INP_COUNTER PROC
;цикл ввода числа элементов в массиве
INP:
LEA DX, MSG_CARR ;перенос каретки
CALL PRINT_MSG
LEA DX, MSG_COUNT ;вывести приглашение к вводу
CALL PRINT_MSG
LEA DX, STR_BUFF ;загрузка буфера ввода строки
CALL INPUT_STR ;ввод строки
LEA SI, STR_BUFF+2 ;загрузка адреса строки
CALL STR_TO_HEX ;вызвать процедуру преобразования
;AX = число
CMP FERR, 1 ;проверить флаг ошибки
JE MERR1 ;перейти на метку MERR
CMP AX, 255 ;сравнить AX с 255
JA MERR1 ;перейти по метке если больше
JMP EXT_COUNTER
MERR1:
CALL PRINT_ERROR ;вывести сообщение о ошибке
JMP INP ;повтор ввода количества
EXT_COUNTER:
RET
INP_COUNTER ENDP
;Процедура ввода чисел в массив
;ВХОД: DI — адрес массива для записи чисел
;CX — число элементов
;DX — адрес сообщения перед вводом
INP_ARRAY PROC
PUSH DX
MOV COUNTER, 0 ;обнулить счетчик введенных чисел
;цикл ввода чисел в массив
INP_ARR:
POP DX
CALL PRINT_MSG ;вывести на экран «X1[«
PUSH DX
PUSH DI ;сохранить в стек адрес массива
LEA DI, STR_BUFF+2 ;загрузить адрес начала строки
MOV AX, [COUNTER] ;загрузка индекса
CALL HEX_TO_STR ;преобразовать счетчик ввода в строку
LEA DX, STR_BUFF+2
CALL PRINT_MSG ;вывести счетчик X1[ n
LEA DX,MSG_IND
CALL PRINT_MSG ;закрыть индекс X1 [ n ]
POP DI ;восстановить из стека адрес
;ввод строки ,проверка корректности ввода, преобразование в число и запись в выходной массив
LEA DX, STR_BUFF ;загрузка адреса массива ввода
CALL INPUT_STR ;ввод строки
LEA SI, STR_BUFF+2 ;загрузка адреса строки
CALL STR_TO_HEX ;преобразование в число (выход AX= число)
CMP FERR, 1 ;проверка флага ошибки
JE MERR2 ;перейти на вывод ошибки если 1
MOV [DI], AX ;записать число в выходной массив
INC COUNTER ;увеличить счетчик чисел
ADD DI, 2 ;модификация адреса
LEA DX, MSG_CARR ;загрузка адреса переноса
CALL PRINT_MSG ;перенос на сл.строку
LOOP INP_ARR ;продолжать цикл пока cx!=0
JMP EXT_INP_ARRAY ;перейти на ввод кол-ва элементов сл.массива
MERR2:
CALL PRINT_ERROR ;вывести ошибку ввода
JMP INP_ARR ;перейти в начало цикла
EXT_INP_ARRAY:
POP DX
RET
INP_ARRAY ENDP
;Процедура вывода чисел из массива на экран
;ВХОД: SI — адрес массива чисел
;CX — число элементов
;DX — адрес сообщения перед выводом
OUT_ARRAY PROC
PUSH DX
CMP CX, 0 ;число найденных элементов
JE NOT_ITEM1 ;если их нет, то перейти по метке NOT_ITEM1
MOV COUNTER, 0 ;обнулить счетчик выведенных чисел
OUTARR:
;подготовка к выводу
POP DX
CALL PRINT_MSG ;вывести Y1[
PUSH DX
INC COUNTER ;+1 к счетчику чисел
LEA DI, STR_BUFF+2 ;адрес для преобразованной строки
MOV AX, [COUNTER] ;в AX число для преобразования
CALL HEX_TO_STR ;вызвать преобразование в строку
LEA DX, STR_BUFF+2
CALL PRINT_MSG ;вывести строку Y[ n
LEA DX, MSG_IND
CALL PRINT_MSG ;закрыть индекс Y [ n ]
;преобразование числа выходного массива
LEA DI, STR_BUFF+2 ;адрес строки
MOV AX, [SI] ;поместить в AX
CALL HEX_TO_STR ;вызвать процедуру преобразования
ADD SI, 2 ;изменить адрес на сл.число
LEA DX, STR_BUFF+2
CALL PRINT_MSG ;вывести число
LEA DX, MSG_CARR
CALL PRINT_MSG ;перенос на сл.строку
LOOP OUTARR ;продолжать цикл пока cx!=0
JMP EXT_OUT_ARRAY
NOT_ITEM1:
CALL PRINT_ITEM ;отсутствия чисел в массиве
EXT_OUT_ARRAY:
POP DX
RET
OUT_ARRAY ENDP
;Подпрограмма преобразование строки в число
;ВХОД: SI=адрес строки
;ВЫХОД: AX=число
STR_TO_HEX PROC
PUSH CX ;сохранить счетчик цикла в стек
MOV FERR, 0 ;Обнуление
MOV MINUS, 0 ;флагов
MOV BX, 10 ;множитель
XOR AX, AX ;обнуление регистров
XOR DX, DX
XOR CX, CX
CMP BYTE PTR [SI], 13
JE INP_ERR ;если 1 символ «enter» ,перейти
CMP BYTE PTR [SI], ‘-‘
JNE MNEXT1 ;если 1 символ не «-» ,перейти MOV MINUS, 1 ;установить флаг минуса
INC SI ;перейти к след символу строки
CMP BYTE PTR [SI], 13 ;если второй символ «enter»,
JE INP_ERR
MNEXT1:
CMP BYTE PTR [SI], 13 ;Проверка конца строки
JE MNEXT2 ;если символ enter то перейти MNEXT2
CMP BYTE PTR [SI], ‘0’
JB INP_ERR ;если символ меньше 0, то ошибка
CMP BYTE PTR [SI], ‘9’
JA INP_ERR ;если символ больше 9, то ошибка
JMP NEXT_SYM ;иначе перейти по метке преобразования
INP_ERR:
MOV FERR, 1 ;установить флаг ошибки
JMP EXT_CONVERTED ;перейти на выход
NEXT_SYM:
MUL BX ;умножить AX на 10
SUB BYTE PTR [SI], ‘0’ ;отнять от символа 30h
MOV CL, BYTE PTR [SI] ;записать цифру в CL
ADD AX, CX ;прибавить цифру к общему числу
INC SI ;перейти к следующему символу строки
JMP MNEXT1 ;перейти на метку MNEXT1
MNEXT2:
CMP DX, 0 ;проверить был ли перенос при умножени
JNE MNEXT3 ;если dx не 0, то перейти к установке ошибки
CMP MINUS, 1
JNE NOT_MINUS ;если положительное перейти по метке NOT_MINUS
CMP AX, 32768 ;сравнить с максимального отрицательным
JA MNEXT3 ;если больше, установить ошибку
NEG AX ;смена знака числа
JMP EXT_CONVERTED ;перейти к выходу из цикла преобразования
NOT_MINUS:
CMP AX, 32767 ;сравнить с максимальным
JBE EXT_CONVERTED ;если меньше или равно,
MNEXT3:
MOV FERR, 1 ;установка флага ошибки
EXT_CONVERTED:
POP CX ;восстановить из стека cx
RET
STR_TO_HEX ENDP
;Подпрограмма преобразования числа в строку
;ВХОД : AX = число для преобразования
;ВЫХОД: DI = адрес начала строки для вывода
HEX_TO_STR PROC
PUSH CX ; сохранить в стек счетчик
XOR CX, CX
MOV BX, 10 ;делитель 10
TEST AX, 08000H ;проверить знак числа
JZ MNEXT4
MOV BYTE PTR [DI], ‘-‘ ;занести в строку —
NEG AX ;преобразовать в положительное
INC DI ;перейти к следюущему символу
MNEXT4:
XOR DX, DX ;остаток от деления в 0
DIV BX ;разделить число на 10
ADD DL, ‘0’ ;преобразовать остаток в символ
PUSH DX ;поместить символ в стек
INC CX ;увеличить счетчик символов +1
CMP AX, 0 ;если делимое еще не равно 0
JNE MNEXT4 ;продолжать деление
;записть символов в массив
MNEXT5:
POP DX ;достать из стека символ
MOV [DI], DL ;поместить в массив
INC DI ;изменить адрес на сл.ячейку
LOOP MNEXT5 ;продолжать цикл
MOV BYTE PTR [DI], ‘$’ ;записать в конце строки символ конца строки
POP CX ;восстановить CX
RET
HEX_TO_STR ENDP
CODE ENDS
END START
Заключение
В данной работе разработана программа на языке Assembler, выбирающая из двух массивов слов со знаком элементы, входящие в заданный диапазон. Программа написана в двух вариантах: без интерфейса и с использованием интерфейса.
Список использованных источников
1 Комаров, В. М. Микропроцессорны
2 Калашников, О. А. Ассемблер – это просто. Учимся программировать. – 2-е изд., перераб. и доп. – СПБ.: БХВ-Петербург, 2011. – 336 c.