Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Микропроцессорные системы (книга Комаров) / Проектирование МП систем (ч 3).doc
Скачиваний:
106
Добавлен:
08.03.2015
Размер:
772.1 Кб
Скачать

Кодирование программы для ввода данных в озу

Пример 6.13:

Выполнить кодирование программы работы устройства для ввода данных в ОЗУ.

Для решения поставленной задачи необходимо использовать результаты проектирования программы, полученные в примерах 6.4 6.7. При этом принятое кодирование данных представлено в таблице 6.4, а алгоритмы программы и программных модулейна рис. 6.376.50. Из их анализа следует, что многие модули выполняют ввод/вывод данных, что требует разработки архитектуры ввода/вывода проектируемого устройства для их кодирования. Архитектура ввода данных приведена на рис. 6.57, а архитектура выводана рис. 6.58.

Для уменьшения аппаратурных затрат двоичные индикаторы "Тип ввода" ("Адрес"/"Данные") подключены к свободным разрядам Q7,Q6 клавиатурного порта вывода KbdPort. Клавиатурный порт ввода имеет то же имя KbdPort (тот же адрес), что и клавиатурный порт вывода, так как обращение к ним осуществляется разными управляющими сигналами (см. рис. 6.57,а).

Рис. 6.57. Архитектура ввода устройства для ввода данных в ОЗУ:

а) ввод с клавиатуры; б) ввод управляющих переключателей

Состояние управляющих переключателей вводится через порт ввода ModePort с нулевым кодированием активных значений (см. рис. 6.57,б).

а) б)

Рис. 6.58.Архитектура вывода устройства для ввода данных в ОЗУ:

а) вывод на индикаторы дисплеев; б) таблица преобразования

В связи с использованием статической индикации каждый из знакосинтезирующих индикаторов дисплеев "Адрес" и "Данные" подключен к отдельному порту вывода. При этом порт младшего разряда дисплея "Адрес" имеет имя (адрес) ADispPort, а дисплея "Данные" DDispPort. Адреса портов более старших разрядов последовательно увеличиваются на 1 относительно адреса младшего порта (см. рис. 6.58,а).

Свечение сегмента индикатора в приведенной схеме вызывается нулевым значением управляющего сигнала. С учетом этого в таблице на рис. 6.58,б представлены управляющие 7-сегментные коды, обеспечивающие отображение соответствующего графического знака в разряде дисплея. При этом отображаемые символы шестнадцатиричных цифр приведены в колонке Hex в стандартном начертании. Эта таблица используется для преобразования двоичного кода отображаемой 16-ричной цифры из формата 8421 в семисегментный код.

Имея алгоритмы программы и программных модулей (см. рис. 6.7-6.50), структуру данных (см. табл. 6.4) и архитектуру ввода/вывода (см. рис. 6.57, 6.58), можно полностью разработать исходный текст проектируемой программы.

;ПРОГРАММА РАБОТЫ УСТРОЙСТВА ДЛЯ ВВОДА ДАННЫХ В ОЗУ

NAMEDataInputProgram

; ОПИСАНИЕ ПОИМЕНОВАННЫХ КОНСТАНТ

KbdPort = 0 ;Адреса портов

ModePort = 1 ;архитектуры

ADispPort = 2 ;ввода/вывода

DDispPort = 6

NMAX = 50 ;Константа подавления дребезга

; ОПИСАНИЕ ДАННЫХ

Data1 SEGMENTAT 1000h

Mode DB ? ;Структура

InType DB? ;данных

AddrInc DB? ;программы

AddrDec DB?

KbdImage DB4DUP(?)

NextDig DB?

Addr DW?

BufData DB?

DataDisp DB2DUP(?)

AddrDisp DB 4DUP(?)

EmpKbd DB?

KbdErr DB?

RAMErrD DB?

RAMErrA DB ?

; ОПИСАНИЕ СЛУЖЕБНЫХ ЯЧЕЕК

ATstBuff DW17DUP(?) ;Буфер адресного теста

MesBuff DB? ;Буфер сообщения "Тип ввода"

OldAddrModif DB? ;Буфер старой модификации

Data1 ENDS;адреса

Data2 SEGMENTAT 2000h

RAMData DW32768DUP(?) ;Формируемые данные

Data2 ENDS

; ОПИСАНИЕ СТЕКА

Stack SEGMENTAT 1000h

ORG 100h ;Смещение за зону данных

DW10 DUP(?)

StkTop LABEL WORD

Stack ENDS

; ОПИСАНИЕ ВЫПОЛНЯЕМЫХ ДЕЙСТВИЙ

Code SEGMENT

ASSUMECS:Code, DS:Data1, ES:Data2, SS:Stack

; ОПИСАНИЕ ПРОГРАММНЫХ МОДУЛЕЙ

; Модуль "Функциональная подготовка"

FuncPrep PROCNEAR;ГСА по рис. 6.50

MOV InType, 0 ;Тип ввода="Адрес"

MOV KbdErr, 0 ;Очистка флага ошибки

;ввода с клавиатуры

MOV BX, 0 ;Очистка адреса

MOV Addr, BX

MOV AL, ES:[BX] ;Чтение байта из RAMData ;по нулевому адресу

MOV BufData, AL ;Запись байта в буфер

MOV OldAddrModif, 18h ;Старые команды "+1", ;"1" отсутствуют

RET

FuncPrep ENDP

; 1. Модуль "Тестовый контроль ОЗУ по ШД"

DTstContr PROC NEAR ;ГСА по рис. 6.39

;Подготовка

MOV RAMErrD, 0 ;Сброс флага ошибки

LEA BX, RAMData ;Загрузка адреса и

MOV CX, LENGTHRAMData ;счетчика циклов

DTC2:MOV AX, ES:[BX] ;Сохранение ячейки

MOV ES:[BX], 5555h ;Запись в ячейку

CMP ES:[BX], 5555h ;Записано ?

JNE DTC1 ;Переход, если нет

MOV ES:[BX], 0AAAAh ;Запись в ячейку

CMP ES:[BX], 0AAAAh ;Записано ?

JNE DTC1 ;Переход, если нет

MOV ES:[BX], AX ;Восстановление ячейки

ADD BX, 2 ;Модификация адреса

LOOP DTC2 ;Все ячейки ? Переход, ;если нет

JMP SHORT DTC3 ;На выход

DTC1:MOV RAMErrD, 0FFh ;Установка флага ошибки

DTC3:RET

DTstContr ENDP

; 2. Модуль "Тестовый контроль ОЗУ по ША"

ATstContr PROC NEAR;ГСА по рис. 6.40

;Подготовка к записи

MOV RAMErrA, 0 ;Сброс флага ошибки

MOV BX, 0 ;Загрузка адреса ячейки влияния STC ;и счетчика циклов

LEA SI, ATstBuff ;Загрузка адреса буфера

ATC1:MOV AX, [BX] ;Сохранение ячейки

MOV [SI], AX ;влияния

MOV [BX],BX ;Запись адреса в ячейку влияния

ADD SI, 2 ;Модификация адреса буфера

RCL BX, 1 ;Модификация адреса ячейки ;влияния и счетчика циклов

OR BX, BX ;Все ячейки влияния ?

JNZ ATC1 ;Переход, если нет

;Подготовка к анализу

MOV BX, 0 ;Загрузка адреса ячейки влияния

STC ;и счетчика циклов

LEA SI, ATstBuff ;Загрузка адреса буфера

ATC3:MOV AX, [BX] ;Чтение из ячейки влияния

CMP AX, BX ;Содержимое = адресу ?

JNE ATC2 ;Переход, если нет

MOV AX, [SI] ;Восстановление ячейки MOV [BX], AX ;влияния

ADD SI, 2 ;Модификация адреса буфера

RCL BX, 1 ;Модификация адреса ячейки ;влияния и счетчика циклов

OR BX, BX ;Все ячейки влияния ?

JNZ ATC3 ;Переход, если нет

JMP SHORT ATC4 ;На выход

ATC2: MOV RAMErrA, 0FFh;Установка флага ошибки

ATC4:RET

ATstContr ENDP

;3. Модуль "Вывод сообщений об ошибках"

ErMesOut PROC NEAR;ГСА по рис. 6.41

CMP KbdErr, 0FFh ;Ошибка клавиатуры ?

JZ EMO1 ;Переход, если да

CMP RAMErrD, 0FFh ;Ошибка ОЗУ по ШД ?

JZ EMO2 ;Переход, если да

CMP RAMErrA, 0ffh ;Ошибка ОЗУ по ША ?

JNZ EMO3 ;Переход, если нет

; Вывод сообщения об отказе ОЗУ по ША "ErОП A"

CALL ErrRAM ;Вывод сообщения ErОП

MOV AL, 11h ;Вывод знака А

OUT DDispPort, AL

JMP SHORT EMO3 ;На выход

; Вывод сообщения об отказе ОЗУ по ШД "ErОП d"

EMO2:CALL ErrRAM ;Вывод сообщения ErОП

MOV AL, 85h ;Вывод знака d

OUT DDispPort, AL

JMP SHORT EMO3 ;На выход

; Вывод сообщения об ошибке ввода с клавиатуры "Err НБ"

EMO1:MOV AL, 61h ;Вывод знака E

OUT ADispPort+3, AL

MOV AL, 0F5h ;Вывод знака r

OUT ADispPort+2, AL

OUT ADispPort+1, AL ;Вывод знака r

MOV AL, 0FFh ;Гашение знака

OUT ADispPort, AL

MOV AL, 91h ;Вывод знака H

OUT DDispPort+1, AL

MOV AL, 41h ;Вывод знака Б

OUT DDispPort, AL

EMO3:RET

ErMesOut ENDP

; Подмодуль "Вывод сообщения ErОП"

ErrRAM PROC

MOV AL, 61h ;Вывод знака E

OUT ADispPort+3, AL

MOV AL, 0F5h ;Вывод знака r

OUT ADispPort+2, Al

MOV AL, 03h ;Вывод знака О

OUT ADispPort+1, AL

MOV AL, 13h ;Вывод знака П

OUT ADispPort, AL

MOV AL, 0FFh ;Гашение знака

OUT DDispPort+1, AL

RET

ErrRAM ENDP

; 4. Модуль "Ввод режимов"

ModeInput PROC NEAR;ГСА по рис. 6.42,а

;Подготовка

MOV Mode, 0 ;Режим="Ввод"

MOV AddrInc, 0 ;Сброс флагов

MOV AddrDec, 0 ;модификации адреса

IN AL, ModePort ;Ввод переключателей

MOV DX, ModePort ;Передача параметра

CALL VibrDestr ;Гашение дребезга

TEST AL, 01h ;"Режим" = "Просмотр"?

JNZ MI1 ;Переход, если нет

MOV Mode, 0FFh ;Режим = "Просмотр"

JMP SHORT MI2

MI1:TEST AL, 02h ;"Тип ввода" = "Адрес"?

JZ MI2 ;Переход, если да

TEST AL, 04h ;"Тип ввода" = "Данные"?

JNZ MI3 ;Переход, если нет

MOV InType, 0FFh ;Тип ввода = "Данные"

JMP SHORT MI3

MI2:MOV InType, 0 ;Тип ввода = "Адрес"

MI3:MOV AH, OldAddrModif ;Чтение старых значений

;сигналов "+1", "1"

MOV OldAddrModif, AL ;Сохранение текущих ;значений сигналов"+1","1"

XOR AL, AH ;Выделение ПФ сигналов

AND AL, AH ;"+1","1"

TEST AL, 08h ;ПФ"Адрес"="+1"?

JNZ MI4 ;Переход, если нет

MOV AddrInc, 0FFh ;Модификация адреса="+1"

MI4:TEST AL, 10h ;ПФ"Адрес"="1"?

JNZ MI5 ;Переход, если нет

MOV AddrDec, 0FFh ;Модификация адреса="1"

MI5:RET

ModeInput ENDP

; Подмодуль "Гашение дребезга"

VibrDestr PROC;ГСА по рис. 6.42,в

VD1:MOV AH, AL ;Сохранение исходного состояния

MOV BH, 0 ;Сброс счетчика повторений

VD2: IN AL, DX ;Ввод текущего состояния

CMP AH, AL ;Текущее состояние=исходному?

JNE VD1 ;Переход, если нет

INC BH ;Инкремент счетчика повторений

CMP BH, NMAX ;Конец дребезга?

JNE VD2 ;Переход, если нет

MOV AL, AH ;Восстановление местоположения

RET ;данных

VibrDestr ENDP

; 5. Модуль "Вывод сообщения о типе ввода"

InTpMesOut PROC NEAR;ГСА по рис. 6.43

MOV AL, 40H ;Сообщение "Тип ввода"="Адрес"

CMP InType, 0 ;Тип ввода = "Адрес"?

JE ITMO1 ;Переход, если да

MOV AL, 80h ;Сообщение "Тип ввода"="Данные"

ITMO1:MOV MesBuff, AL ;Сохранение сообщения

;"Тип ввода"

OR AL, 0Fh ;Вывод сообщения

OUT KbdPort, AL ;"Тип ввода"

RET

InTpMesOut ENDP

; 6. Модуль "Ввод с клавиатуры"

KbdInput PROC NEAR;ГСА по рис. 6.44

;Подготовка

LEA SI, KbdImage ;Загрузка адреса,

MOV CX, LENGTHKbdImage ;счетчика циклов и

MOV BL, 0FEh ;номера исходной строки

KI4:MOV AL, BL ;Выбор строки

AND AL, 3Fh ;Объединение номера с

OR AL, MesBuff ;сообщением "Тип ввода"

OUT KbdPort, AL ;Активация строки

IN AL, KbdPort ;Ввод строки

AND AL, 0Fh ;Включено?

CMP AL, 0Fh

JZ KI1 ;Переход, если нет

MOV DX, KbdPort ;Передача параметра

CALL VibrDestr ;Гашение дребезга

MOV [SI], AL ;Запись строки

KI2:IN AL, KbdPort ;Ввод строки

AND AL, 0Fh ;Выключено?

CMP AL, 0Fh

JNZ KI2 ;Переход, если нет

CALL VibrDestr ;Гашение дребезга

JMP SHORTKI3

KI1:MOV [SI], AL ;Запись строки

KI3:INC SI ;Модификация адреса

ROL BL, 1 ;и номера строки

LOOP KI4 ;Все строки? Переход, если нет

RET

KbdInput ENDP

; 7. Модуль "Контроль ввода с клавиатуры"

KbdInContr PROC NEAR;ГСА по рис. 6.45

;Подготовка

LEA BX, KbdImage ;Загрузка адреса

MOV CX, 4 ;и счетчика строк

MOV EmpKbd, 0 ;Очистка флагов

MOV KbdErr, 0

MOV DL, 0 ;и накопителя

KIC2:MOV AL, [BX] ;Чтение строки

MOV AH, 4 ;Загрузка счетчика битов

KIC1:SHR AL, 1 ;Выделение бита

CMC ;Подсчет бита

ADC DL, 0

DEC AH ;Все биты в строке?

JNZ KIC1 ;Переход, если нет

INC BX ;Модификация адреса строки

LOOP KIC2 ;Все строки? Переход, если нет

CMP DL, 0 ;Накопитель = 0?

JZ KIC3 ;Переход, если да

CMP DL, 1 ;Накопитель = 1?

JZ KIC4 ;Переход, если да

MOV KbdErr, 0FFh ;Установка флага ошибки

JMP SHORTKIC4

KIC3:MOV EmpKbd, 0FFh ;Установка флага

;пустой клавиатуры

KIC4:RET

KbdInContr ENDP

; 8. Модуль "Преобразование очередной цифры"

NxtDigTrf PROC NEAR;ГСА по рис. 6.46

CMP EmpKbd, 0ffh ;Пустая клавиатура?

JZ NDT1 ;Переход, если да

CMP KbdErr, 0FFh ;Ошибка клавиатуры?

JZ NDT1 ;Переход, если да

;Подготовка

LEA BX, KbdImage ;Загрузка адреса

MOV DX, 0 ;Очистка накопителей

;кода строки и столбца

NDT3: MOV AL, [BX] ;Чтение строки

AND AL, 0Fh ;Выделение поля клавиатуры

CMP AL, 0Fh ;Строка активна?

JNZ NDT2 ;Переход, если да

INC DH ;Инкремент кода строки

INC BX ;Модификация адреса

JMP SHORTNDT3

NDT2:SHR AL, 1 ;Выделение бита строки

JNC NDT4 ;Бит активен? Переход, если да

INC DL ;Инкремент кода столбца

JMP SHORTNDT2

NDT4:MOV CL, 2 ;Формирование двоичного

SHL DH, CL ;кода цифры

OR DH, DL

MOV NextDig, DH ;Запись кода цифры

NDT1:RET

NxtDigTrf ENDP

; 9. Модуль "Формирование информации"

InfoForm PROC NEAR;ГСА по рис. 6.47

MOV AL, KbdErr ;Есть ошибки?

OR AL, RAMErrD

OR AL, RAMErrA

JNZ InF1 ;Переход, если да

CMP EmpKbd, 0FFh ;Пустая клавиатура?

JNE InF2 ;Переход, если нет

MOV BX, Addr ;Чтение адреса

CMP AddrInc, 0FFh ;Инкремент адреса?

JNE InF3 ;Переход, если нет

INC BX ;Инкремент адреса

JMP SHORTInF4

InF3:CMP AddrDec, 0ffh ;Декремент адреса?

JNE InF1 ;Переход, если нет

DEC BX ;Декремент адреса

InF4:CMP Mode, 0 ;Режим = "Ввод"?

JNE InF5 ;Переход, если нет

MOV DL, BufData ;Чтение данных из буфера

MOV SI, Addr ;Запись данных по

MOV ES:[SI], DL ;старому адресу

JMP SHORTInF5

InF2:CMP InType, 0 ;Тип ввода="Адрес"?

JNE InF6 ;Переход, если нет

MOV BX, Addr ;Чтение адреса

MOV CL, 4 ;Сдвиг адреса на

SHL BX, CL ;тетраду

OR BL, NextDig ;Включение очередной

;цифры в адрес

InF5:MOV DL, ES:[BX] ;Чтение данных по новому адресу

MOV Addr, BX ;Запись нового адреса

JMP SHORTInF7

InF6:MOV DL, BufData ;Чтение данных из буфера

MOV CL, 4 ;Сдвиг данных на тетраду

SHL DL, CL

OR DL, NextDig ;Включение очередной

;цифры в данные

InF7:MOV BufData, DL ;Запись новых данных в буфер

InF1:RET

InfoForm ENDP

; 10. Модуль "Формирование массива отображения"

DispForm PROC NEAR;ГСА по рис. 6.48

; Этот модуль реализован для формирования лишь одного массива отобра-

;жения. Формирование двух массивов DataDisp и AddrDisp должно осуществля-

;ться путем его двукратного вызова с передачей соответствующих параметров

;перед каждым вызовом

; Входные параметры:

; BX адрес входных данных

; SI адрес массива отображения

; CH количество цифр в массиве

MOV AL, KbdErr ;Есть ошибки?

OR AL, RAMErrD

OR AL, RAMErrA

JNZ DF1 ;Переход, если да

MOV AX, [BX] ;Чтение данных

DF2:MOV DX, AX ;Копирование данных

AND AL, 0Fh ;Выделение младшей тетрады

MOV [SI], AL ;Запись в память

MOV AX, DX ;Восстановление данных

MOV CL, 4 ;Сдвиг данных

SHR AX, CL ;на тетраду

DEC CH ;Все цифры

JNZ DF2 ;Переход, если нет

DF1:RET

DispForm ENDP

; 11. Модуль "Вывод числовой информации"

NumInfOut PROC NEAR ;ГСА по рис. 6.49

; Этот модуль реализован для вывода информации из одного массива отобра-

;жения на соответствующий знакосинтезирующий дисплей. Вывод информации

;на оба дисплея ("Адрес", "Данные") должен осуществляться путем его двукрат-

;ного вызова с передачей соответствующих параметров перед каждым вызовом.

; Входные параметры:

; SI адрес входного массива отображения

; DX номер младшего порта дисплея

; CX количество выводимых знаков

MOV AL, KbdErr ;Есть ошибки?

OR AL, RAMErrD

OR AL, RAMErrA

JNZ NIO1 ;Переход, если да

LEA BX, TrfTabl ;Загрузка адреса таблицы

;преобразования

NIO2:MOV AL, [SI] ;Чтение цифры

XLAT ;Преобразование цифры

OUT DX, AL ;Вывод цифры в порт

INC SI ;Модификация адреса

INC DX ;и номера порта

LOOP NIO2 ;Все цифры? Переход, если нет

NIO1:RET

NumInfOut ENDP

; Таблица преобразования (см. рис. 6.58,б)

TrfTabl DB03h,9Fh,25h,0Dh,99h,49h,41h,1Fh

DB01h,09h,11h,0C1h,63h,85h,61h,71h

; МАКРОУРОВЕНЬ ПРОГРАММЫ ;ГСА по рис. 6.38

Start:

;Системная подготовка

MOV AX, Data1 ;Инициализация

MOV DS, AX ;сегментных

MOV AX, Data2 ;регистров

MOV ES, AX

MOV AX, Stack

MOV SS, AX

LEA SP, StkTop ;и указателя стека

CALL FuncPrep ;Функциональная подготовка

Cont:CALL DTstContr ;Тест ОЗУ по ШД

CALL ATstContr ;Тест ОЗУ по ША

CALL ErMesOut ;Вывод сообщений об ошибках

CALL ModeInput ;Ввод режимов

CALL InTpMesOut ;Вывод сообщения о типе ввода

CALL KbdInput ;Ввод с клавиатуры

CALL KbdInContr ;Контроль ввода с клавиатуры

CALL NxtDigTrf ;Преобразование очередной

;цифры

CALL InfoForm ;Формирование информации

LEA BX, BufData ;Передача параметров

LEA SI, DataDisp ;для формирования массива

MOV CH, 2 ;отображения данных

CALL DispForm ;Формирование массива

;отображения

LEA BX, Addr ;Передача параметров

LEA SI, AddrDisp ;для формирования массива

MOV CH, 4 ;отображения адреса

CALL DispForm ;Формирование массива

;отображения

LEA SI, DataDisp ;Передача параметров

MOV DX, DDispPort ;для вывода информации на

MOV CX, 2 ;дисплей "Данные"

CALL NumInfOut ;Вывод числовой информации

LEA SI, AddrDisp ;Передача параметров для

MOV DX, ADispPort ;вывода информации

MOV CX, 4 ;на дисплей "Адрес"

CALL NumInfOut ;Вывод числовой информации

JMP Cont ;Замыкание программного кольца

; Две нижеследующих строки необходимы для начального запуска програм-

;мы в составе МПС. Они не используются при работе с программой в составе

;персонального компьютера.

ORGSTART_OFFSET ;Эти строки обеспечивают

JMP FAR PTRStart ;начальный запуск программы

;при включении устройства

Code ENDS

ENDStart

Пусковая команда программы JMP FAR PTRStart должна располагаться в ячейках ПЗУ с физическим адресом FFFF0h, который первым появляется на ША после включения питания. Для этого в исходном тексте программы она должна находиться по адресу трансляции с внутрисегментным смещением START_OFFSET, которое с учетом базового (начального) адреса сегмента программного кода обеспечит формирование требуемого пускового физического адреса. Учитывая принцип вычисления физического адреса памяти (см. подраздел 2.2.6) и размещение ПЗУ в самых старших адресах, можно получить формулу для вычисления смещения STARTOFFSET, которая имеет вид:

STARTOFFSET = VROM 16,

где VROM объем ПЗУ МПС в байтах.

Необходимый объем памяти для размещения программного кода определяется после первоначальной трансляции программы с произвольным числовым значением смещения STARTOFFSET. После этого с учетом используемых ИМС постоянной памяти выбирается объем ПЗУ VROMи точно рассчитывается значение смещения STARTOFFSET. Далее оно вносится в исходный текст программы, и выполняется ее повторная трансляция.

Пример 6.14:

Определить внутрисегментное стартовое смещение STARTOFFSET для программы ввода данных в ОЗУ, если в результате ее первоначальной трансляции объем сегмента программного кода составил 804 байта.

Для размещения сегмента программного кода размером 804 байта целесообразно использовать ПЗУ объемом 2 кбайт, построенное на ИМС К573РФ5. Отсюда VROM = 2К = 2048. Представляя все числа в 16-ричной форме, получим

VROM =800h, 16=10h, STARTOFFSET = 800h10h=7F0h.

В процессе трансляции и компоновки выявляются и исправляются все синтаксические ошибки, содержащиеся в исходном тексте разрабатываемой программы. В результате этого будет получен исходный текст и листинг программы, не содержащие синтаксических ошибок. Однако, это отнюдь не значит, что полученная программа свободна от ошибок вообще. Все остальные ошибки выявляются и устраняются на этапе тестирования и отладки программы.