Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
екция: Элементы системного программирования. Прерывания. Резидентные программы 7 из 7 с.
[0.1] Элементы системного программирования на Паскале [0.2] Распределение памяти [0.3] Специальные адреса памяти [0.4] Переменная Absolute [0.5] Массивы Mem [0.6] Прерывания [0.7] Обработка прерываний [0.8] Использование прерываний в Паскале [0.9] Резидентная программа [0.10] Контрольные вопросы |
Лекция №№ 26-27
Системным программированием называют разработку программ, которые выполняют действия, возлагаемые на ОС. Это операции с файлами, управление выполнением программ, работа с устройствами и т.д.
Операционная система представляет собой программный комплекс (набор взаимосвязанных программ), который выполняет две основные функции:
ОС MS-DOS работает только в реальном режиме. Во всех модернизациях своего микропроцессора (МП) фирма Intel поддерживает этот режим, в котором:
Основными элементами системного программирования являются регистры, сегменты и прерывания.
Регистр это внутреннее запоминающее устройство процессора для временного хранения обрабатываемой или управляющей информации. В Паскале имеется специальный тип Registers, который описывается следующим образом:
type Registers = record {Registers record used by Intr and MsDos}
case Integer of
0: (AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags: Word);
1: (AL, AH, BL, BH, CL, CH, DL, DH: Byte);
end;
Сегмент это область памяти размером до 64 Кбайт, которая начинается по любому адресу, кратному 16. В области памяти, выделяемой программе, имеется три основных сегмента:
Прерывание это вызов процедур низкого уровня операционной системы MS-DOS и BIOS.
Первые 640 Кбайт относятся к так называемой стандартной памяти. Следующие 384 Кбайт занимает область верхней памяти, недоступная для прикладных программ MS-DOS и зарезервированная для использования BIOS. Далее следует область расширенной памяти, не представленная на рисунке.
Рис.1. Логическая структура 1-ого Мбайта оперативной памяти
Для своих собственных нужд и пользовательских программ MS-DOS использует 640 Кбайт памяти.
Адрес |
использование памяти |
A0000 |
command.com |
нерезидентная область памяти |
|
резидентные программы |
|
command.com |
|
Драйверы устройств |
|
10000-14000 |
Буферы MS-DOS |
0800-0A00 |
Ядро MS-DOS |
0040 |
Интерфейс BIOS |
0000 |
Векторы прерываний |
Рис.2. Распределение стандартной памяти
В ОС MS-DOS имеются специальные адреса памяти, которые используются системой и с помощью которых можно выполнять, например, операции по обслуживанию периферийных устройств. Эти адреса расположены в сегменте, для доступа к которому используется константа Seg0040.
Таблица 1. Некоторые специальные адреса MS-DOS
смещение |
размер |
Назначение |
$0010 |
word |
список оборудования |
$0017 |
word |
статус клавиатуры |
$0019 |
word |
альтернативный ввод с клавиатуры |
$001A |
word |
вершина буфера клавиатуры |
$001C |
word |
нижняя часть буфера клавиатуры |
$001Е |
16*word |
буфер клавиатуры - кольцевой список |
В таблице 2 приведено описание байта состояния клавиатуры (адрес $0040:$0017). Установка каждого бита в этом байте соответствует наступлению определенного события.
Таблица 2. Байт состояния клавиатуры
Бит |
событие |
0 |
нажата правая клавиша Shift |
1 |
нажата левая клавиша Shift |
2 |
нажата клавиша Ctrl |
3 |
нажата клавиша Alt |
4 |
нажата клавиша ScrollLock |
5 |
нажата клавиша NumLock |
6 |
нажата клавиша CapsLock |
7 |
нажата клавиша Insert |
Шестнадцатеричная константа $DF, в двоичной записи имеющая вид 1101 1111, играет роль маски. Побитовое выполнение логической операции and над этой константой и байтом состояния клавиатуры устанавливает значение 5-го бита (режим NumLock включен) в 0, т.е. отключает его.
В языке Паскаль имеется возможность размещать переменные по конкретным адресам оперативной памяти. Такие переменные называются абсолютными и обычно используются в системных программах. Для описания абсолютных переменных предназначено зарезервированное слово Absolute. Формат:
Var <идентификатор> : <тип> Absolute BA:BS;
где BA базовый адрес сегмента, BS смещение внутри этого сегмента. Например,
Var root : integer Absolute $0000:$01F0;
BA:BS может заменяться на идентификатор другой переменной, тогда вместо BA:BS будет подставлен ее адрес. Таким способом можно выполнять наложение переменных.
Пример. Программа образует строку букв алфавита путем ее увеличения в цикле на одну букву, начиная с латинской буквы a.
Var
str:string[10];
len: byte absolute str; {len налагается на str, т.е. len будет содержать значение первого байта переменной str, содержащего текущую длину строки}
i:integer;
c:char;
Begin
c:='a';
str:='a';
writeln(str);
writeln('length of string =',len);
for i:=1 to 3 do
begin
str:=str+succ(c);
writeln(str);
writeln('length of string =',len);
c:=succ(c);
end;
readln
End.
Результат работы:
a
length of string = 1
ab
length of string = 2
abc
length of string = 3
abcd
length of string = 4
Для работы с абсолютными переменными в языке Паскаль имеется ряд стандартных подпрограмм:
Addr(Id) возвращает адрес расположения первого байта переменной с идентификатором Id. Результат имеет длину два слова и содержит базовый адрес и величину смещения.
Ofs(Id) возвращает величину смещения в сегменте первого байта указанной переменной, процедуры или функции, определяемой Id. Результат имеет целочисленное значение.
Seg(Id) возвращает адрес сегмента, содержащего первый байт переменной с идентификатором Id. Результат имеет целочисленный тип.
CSeg возвращает базовый адрес сегмента кода. Результат имеет целочисленный тип.
DSeg возвращает базовый адрес сегмента данных. Результат имеет целочисленный тип.
В Турбо Паскале имеется пять предварительно объявленных массивов: MEM, MEMW, MEML, PORT и PORTW. Первые три обеспечивают доступ к любому участку оперативной памяти по абсолютному адресу, два других - доступ к портам ввода-вывода.
Компонентами массива MEM являются данные типа BYTE, массива MEMW - типа WORD, массива MEML - типа LONGINT. Обращение к элементам этих массивов, т.е. их индексация, имеет специальный вид: каждый индекс представляет собой абсолютный адрес и состоит из двух выражений типа WORD; первое дает сегментную часть адреса, второе - смещение; выражения разделяются двоеточием. Например:
Меm[$0000:$1000] := 0;
DataMem := MemWfSeg(p):0fs(p)];
MemLong :.= MemL [64 : i*SizeOf (real) ] ;
Как следует из технического описания операционной системы MS-DOS, в памяти по адресу $F000:$FFFE располагается байт-указатель типа компьютера. Следующая программа прочтет этот байт и выведет на экран тип вашего ПК.
Пример
begin
Write (' Тип компьютера: ') ;
case Mem [$FOOO:$FFFE] of
$FF : WriteLn ('PC');
$FE : WriteLn('XT');
$FD : WriteLn('PCjr');
$FC : WriteLn('AT');
$F9 : WriteLn('совместимый с PC')
End;
readln
end.
Компонентами массива PORT являются байты (тип BYTE), а массива PORTW - слова (тип WORD). Индексами этих массивов должно быть выражение типа BYTE, указывающее номер нужного порта. Присвоение значения элементу массива PORT или PORTW приведет к записи в порт, упоминание элемента в выражении - к чтению из порта. Компоненты массивов PORT и PORTW нельзя передавать в качестве параметров процедурам или функциям. Эти идентификаторы не употребляются без индексных выражений.
Пример.
Var z:byte;
Begin
Z:=mem[0000:0001]; {чтение ячейки памяти}
Writeln(z); {вывод считанного значения}
Mem[0000:0001]:=5; {изменение значения ячейки памяти}
Writeln(Mem[0000:0001]) {вывод нового значения}
End.
Когда в память требуется занести или считать по указанному адресу слово (два байта) или двойное слово (четыре байта) используются массивы MemW и MemL соответственно.
Отметим, что для указания базового сегмента и смещения в некоторых случаях удобно использовать стандартные функции Seg и Ofs:
Mem[Seg(<имя_переменной>):Ofs(<имя_переменной>)]:=<значение>.
Операционная система осуществляет управление с помощью прерываний. Прерывание представляет собой сигнал процессору, вырабатываемый программой, каким-либо устройством или самим процессором. Этот сигнал приостанавливает выполнение программы и запускает соответствующую функцию операционной системы для выполнения необходимых системных действий, например ввод-вывод данных или обработка ошибок, с последующим возобновлением выполнения прерванной программы.
Прерывания могут быть внешними и внутренними. Внешние прерывания вызываются внешними по отношению к МП событиями и являются непланируемыми прерываниями. Внутренние прерывания возникают внутри МП во время вычислительного процесса. К их возбуждению приводит 1 из 2-х причин:
Под системой прерываний понимают совокупность программных и аппаратных средств, реализующих механизм прерываний. К аппаратным средствам системы прерываний относятся выводы МП, микросхема программируемого контроллера прерываний, внешние устройства. К программным средствам системы прерываний реального режима относятся:
If - флаг прерываний предназначен для запрещения аппаратных прерываний по входу intr, если if=1, то МП обрабатывает прерывания, если if=0, МП игнорирует сигналы на входе intr.
Tf - флаг трассировки переводит МП в режим покомандной работы.
Обработка прерываний в реальном режиме производится в 3 этапа:
1-ый этап должен обеспечить временное прекращение выполнения текущей программы, при этом должна сохраниться возможность продолжения работы программы после возникновения прерывания. Для этого необходимо учесть состояние разделяемых между программами ресурсов, т.е. регистров МП. Их содержимое необходимо сохранять. Регистры CS, IP, eFlags сохраняются МП автоматически. Сохранение содержимого остальных регистров должно обеспечиваться программистом - в начале программы обработки прерывания до их использования. Наиболее удобным местом хранения регистров является стек. В конце первого этапа МП после включения в стек регистров FLAGS, CS и IP сбрасывает бит флага прерываний, при этом в стек записывается предыдущее значение регистра FLAGS.
2-ой этап заключается в определении источника прерывания и вызова соответствующей команды обработки. В реальном режиме работы МП допускается до 255 источников прерывания. Количество источников ограничивается размером таблицы векторов прерываний. Эта таблица связующее звено между источником прерывания и процедурой обработки. На 2-ом этапе обработки прерываний МП выполняет следующие действия:
3-ий этап восстановления контекста прерванной программы. Т.е приведение стека в состояние, в котором он был сразу до возникновения прерывания. Для этого программист должен выполнить действия по восстановлению регистров и очистке стека. Результатом 3-го этапа является передача управления очередной команде прерванной программы, которая должна была выполниться, если прерывания не было.
Для обеспечения интерфейса с программами операционной системы используется модуль DOS. Для выполнения любого программного прерывания служит процедура
Intr (IntNo : byte; var reg : registers),
где IntNo номер прерывания;
reg переменная типа registers содержит значения регистров до и после входа в процедуру обработки заданного прерывания. Запись Registers представляет собой набор регистров процессора (поля записи).
Специальной разновидностью Intr является процедура MsDos(reg:registers), которая реализует доступ к функциям Dos-прерывания с номером 21h.
Таким образом, вызовы процедур MsDos(reg) и Intr($21, reg) при одинаковой установке значений переменной reg приводят к аналогичным результатам.
Основная последовательность действий при использовании этих функций:
Пример. Установить курсор в позицию (х,у) и вывести строку на экран, используя прерывания.
Uses crt,dos;
Const St:string='Hello$';
Var Reg:registers;
Begin
{установка курсора, используя 2-ую функцию Bios-прерывания $10}
With reg do
Begin
Ah:=2; {функция установки курсора}
Bx:=0; {номер видеостраницы}
Dl:=40; {номер столбца}
Dh:=12; {номер строки}
End;
Intr($10,reg); {установка курсора в позицию (12,40)}
{вывод строки, используя 9ую функцию Dos-прерывания $21}
With reg do
Begin
Ah:=9; {номер функции вывода строки на экран}
DS:=Dseg; {адрес текущего сегмента данных}
Dx:=ofs(st[1]); {смещение строки в сегменте данных}
End;
Msdos(reg);{вывод строки в текущую позицию экрана}
End.
Резидентная программа (или TSR-программа, от англ. Terminate and Stay Resident «завершиться и остаться резидентной») в ОС MS-DOS программа, вернувшая управление оболочке операционной системы (command.com), либо надстройке над операционной системой (Norton Commander и т. п.), но оставшаяся в оперативной памяти персонального компьютера. Резидентная программа активизируется каждый раз при возникновении прерывания, вектор которого эта программа изменила на адрес одной из своих процедур.
В эпоху многозадачных ОС резидентными иногда называют программы, загруженные постоянно и работающие в фоновом режиме. Но применение этого термина некорректно по отношению к многозадачным ОС.
Резидентные программы могут переключать на себя обработку прерываний, например, связанных с выводом на печать или с обращением к клавиатуре и т. д.
Можно встретить множество резидентных программ, предназначенных для загрузки русских шрифтов в память видеоконтроллера, для печати текста, содержащего символы кириллицы, на принтере в графическом режиме, для русификации клавиатуры и т. п. Все эти программы обычно запускаются один раз при загрузке компьютера через файл autoexec.bat .
Другой пример использования резидентных программ: резидентные калькуляторы, справочные базы данных или интегрированные системы, наподобие Borland SideKick. Такие программы тоже обычно запускаются через файл autoexec.bat или при необходимости. Они перехватывают прерывания, предназначенные для работы с клавиатурой. Как только пользователь нажимает заранее определенную комбинацию клавиш, резидентная программа активизируется. Поверх имеющегося на экране изображения выводится диалоговое окно резидентной программы.
Иногда резидентные программы используют вместо загружаемых драйверов для обслуживания нестандартной аппаратуры. В этом случае резидентная программа может встроить свой обработчик, через который все прикладные программы смогут обращаться к аппаратуре.
Аналогично работают резидентные модули некоторых систем управления базами данных (СУБД). Прикладная программа посылает запросы к базе данных через прерывание, устанавливаемое при запуске такой СУБД.
Для обслуживания нестандартной аппаратуры больше подходят загружаемые драйверы. На резидентные программы накладываются многочисленные ограничения, затрудняющие работу программиста. Например, резидентным программам не разрешается использовать прерывания MS-DOS, когда вздумается. Это связано с тем, что MS-DOS с самого начала проектировалась как однозадачная операционная система, поэтому функции прерываний MS-DOS не обладают свойством реентерабельности (повторной входимости).
Способ построения резидентных программ - TSR (Terminate and Stay Resident) позволяет использовать область PSP (Program Segment Prefix) для размещения резидентного кода программы. При разработке TSR - программ стандартными средствами DOS в памяти после завершения программы остается PSP размером 256 байт или, по крайней мере, его часть, если программа использует область FCB (File Control Block) и параметров для собственных нужд. Рассмотрим способ, позволяющий полностью использовать область PSP в интересах резидентной программы и приведем пример такой программы. Данный способ был разработан авторами в начале 1989 года, когда потребовалось загрузить много крохотных TSR - программ, размер которых не превышал PSP.
У программы есть две возможности остаться резидентной в памяти - использовать прерывание INT 27h или функцию 31h прерывания INT 21h .
Для использования прерывания INT 27h сегментный регистр CS должен указывать на PSP программы. При этом в регистр DX следует записать смещение последнего байта программы плюс один байт.
Нетрудно заметить, что этот способ больше всего подходит для com-программ, так как с помощью прерывания INT 27h невозможно оставить в памяти резидентной программу длиннее 64 Кбайт.
Другой, более удобный, способ заключается в вызове функции 31h прерывания INT 21h . В регистре AL можно указать код завершения программы, регистр DX должен содержать длину резидентной части программы в параграфах. Здесь уже нет указанного выше ограничения на размер программы.
Для того чтобы оставить резидентной в памяти программу, размер которой превышает 64 Кбайт, можно использовать только последний метод. Но не стоит увлекаться большими резидентными программами, так как занимаемая ими память нужна другим программам.