Содержание

1 Постановка задачи………………………………………………………………...3

2 Разработка программы без интерфейса………………………………………….4

2.1 Спецификация задачи……………………………………………………………4

2.2 Организация данных…………………………………………………………….4

2.3 Разработка алгоритмов……………………………………………………….….5

2.4 Текст программы………………………………………………………………… 7

3 Разработка программы с интерфейсом..…………………..……………………. 9

3.1 Спецификация задачи……………………………………………………………9

3.2 Организация данных…………………………………………………………….9

3.3 Разработка алгоритмов……………………………………………………….…10

3.4 Текст программы………………………………………………………………..16

Заключение…………………………………………………………………………29

Список использованных источников……………………………………………..30

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 FIRST ARRAY : ‘

MSG_INP_ARR2 DB  ENTER NUMBERS SECOND ARRAY: ‘

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 изд., перераб. и доп. – Рыбинск: РГАТА, 2004. – 163 c.

2 Калашников, О. А. Ассемблер – это просто. Учимся программировать. – 2-е изд., перераб. и доп. – СПБ.: БХВ-Петербург, 2011. – 336 c.