Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Прогр.на_ЯВУ_уч.пос.DOC
Скачиваний:
24
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆

§8.2. Доступ к аппаратуре Доступ к памяти

В Турбо Паскале можно напрямую обращаться к ячейкам памяти, организованным в три типа предопределенных одномерных массивов и представляющих элементы различного формата:

Mem – Byte,

MemW – Word,

MemL – Longint.

Для доступа к элементам массивов используется специальный синтаксис, состоящий из номера сегмента и номера ячейки памяти, оба типа Word:

Mem[$0040:$0049]:=7;

Data := MemW[Seg(V):Ofs(V)];

Обращение к оперативной памяти по физическим адресам обычно используется для доступа к системной информации DOS и BIOS и разрешено только в однопользовательских операционных системах, например MS-DOS.

Доступ к портам ввода-вывода

В процессорах фирмы Intel используется изолированный ввод-вывод. То есть область адресов памяти отделена от области внешних устройств. Все подключаемые внешние устройства с точки зрения процессора выглядят одинаково и являются портами ввода-вывода.

Для доступа к этим портам используются два предопределенных массива

Port, PortW

соответственно с типами byte и word.

Когда элементу массива Port или PortW присваивается значение, это действие интерпретируется как вывод значения в порт.

Когда элемент массива выступает как операнд в выражении, то доступ к порту понимается как ввод с порта. Например:

{ Разрешение дальнейшей работы контроллера прерываний }

Port[$20]:=$20;

{ Установка в 1 заданных линий порта }

PortW[Base]:=PortW[Base] or Maska;

{ Ожидание установки в 0 старшей линии порта }

While (Port[$82] and $80)=0 do;

Пример доступа к порту клавиатуры для управления движением курсора.

Program Kyrsor;

{ Демонстрационный пример доступа к порту клавиатуры

для управления движением курсора }

Uses Crt; { используется для создания задержки }

Var Mode, { записываемый в порт байт }

Ch:byte; { число, читаемое с клавиатуры }

Begin

Writeln(' Выберите режим ввода символов:');

Writeln(' Задержка перед первым повторением:');

Writeln(' 1 - 250 мс');

Writeln(' 2 - 500 мс');

Writeln(' 3 - 750 мс');

Writeln(' 4 - 1 с');

Repeat

Read(Ch);

Until Ch in [1..4];

Case Ch of

1: Mode:=0;

2: Mode:=$20;

3: Mode:=$40;

4: Mode:=$60;

end;

Writeln(' Частота перемещения, раз/сек:');

Writeln(' 1 - 30');

Writeln(' 2 - 20');

Writeln(' 3 - 10');

Writeln(' 4 - 5');

Writeln(' 5 - 2');

Repeat

Read(Ch);

Until Ch in [1..5];

Case Ch of

2: Mode:=Mode or 4;

3: Mode:=Mode or $0a;

4: Mode:=Mode or $14;

5: Mode:=Mode or $1f;

end;

{ Команда на установку режима }

Port[$60]:=$f3;

{ Задержка на восприятие }

Delay(10);

{ Код режима }

Port[$60]:=Mode;

end.

Работа по прерываниям

Программный интерфейс DOS и BIOS организован в виде обращения к процедурам по прерываниям.

Прерыванием является указание процессору на то, что произошло какое-либо событие и требуется его обработка, называемая реакцией на прерывание.

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

INT n

где n - номер прерывания.

Реакцией процессора на прерывание является выполнение подпрограммы, адрес начала которой, или вектор прерывания, находится в таблице, номер строки которой и есть номер прерывания. Максимальное количество прерываний для процессоров Intel — 256.

К подпрограммам DOS и BIOS доступ осуществляется по прерываниям. Связано это с тем, что в разных версиях адреса начала различных подпрограмм могут начинаться с разных адресов. А так как таблицу векторов прерываний формирует сама ОС, то достаточно только зафиксировать назначение строк таблицы, а ее содержание может изменяться.

В IBM-совместимых компьютерах не все вектора прерываний распределены между событиями и устройствами. Неиспользуемые номера и предназначены для обращения к подпрограммам ОС.

Так как свободных прерываний не много, то по одному вектору может вызываться несколько подпрограмм. Номер подпрограммы, называемый функцией или службой преры­вания, передается в качестве параметра, записываемого в регистр АН. Например, наиболее часто используемое прерывание DOS 21Н имеет 87 служб.

Подпрограммы DOS имеют более высокий уровень обработки информации и часто дополнительно используют прерывания BIOS.

Основные прерывания DOS:

21Н — общие функции DOS;

25Н — безусловное чтение с диска;

26Н — безусловная запись на диск.

Основные прерывания BIOS:

10Н — работа с видеосистемой;

12Н — получение размера основной памяти;

13Н — работа с дисками;

14Н — работа с последовательными портами;

15Н — разнообразные службы;

16Н — работа с клавиатурой;

17Н — работа с принтером;

19Н — перезагрузка компьютера;

1АН — работа с часами реального времени.

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

Процедура, которая будет обслуживать прерывание, должна иметь директиву interrupt и строго фиксированный список параметров:

Procedure <имя> (Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:Word); interrupt;

Допускается отсутствие или задание отдельных параметров. Содержимое регистров процессора передается в процедуру в качестве параметров, поэтому их можно изменять.

Собственно переопределение некоторого прерывания производится обращением к процедуре модуля DOS:

SetIntVec (IntNo:byte; Vector:Pointer);

IntNo — номер прерывания, которое необходимо переопределить;

Vector — адрес новой процедуры обработки прерывания, которая будет запускаться автоматически.

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

GetIntVec (IntNo:byte; Var Vector:Pointer);

которая присваивает второму параметру адрес текущей реакции на прерывание с номером IntNo.

Таким образом, несколько программ могут работать с одним прерыванием: сначала срабатывает новый обработчик, затем управление передается следующему, расположенному по адресу Vector.

Программы, обрабатывающие прерывания, являются специфическими, так как обращение к ним происходит не из сегмента программ, а из таблицы прерываний. Поэтому для них необходимо указывать дальний (межсегментный) вызов директивой компилятора {$F+}.

Пример. Обработка прерывания, возникающего при нажатии клавиш Ctrl–Break.

Program Ctrl_Break;

{ Демонстрационный пример обработки прерывания,

возникающего при нажатии клавиш Ctrl-Break }

Uses Dos;

Const BreakFlag:boolean=False;

Var IntSt:pointer; { Адрес стандартного обработчика }

{$F+}

Procedure CtBr; interrupt;

Begin

BreakFlag:=true;

end;

{$F-}

Begin

{ Запоминаем адрес стандартной реакции }

GetIntVec($1b,IntSt);

SetIntVec($1b,@CtBr);

Writeln('Для окончания нажмите Ctrl-Break');

Repeat

Until BreakFlag;

{ Восстанавливаем первоначальный адрес реакции }

SetIntVec($1b,IntSt)

end.