- •Лучший курс лекций по лучшему языку программирования – языку ассемблера Блок управления памятью (mcb)
- •Программирование на Ассемблере для ibm pc
- •Программная модель 8086
- •Программная модель мп
- •Сегментная память
- •Вывод на экран
- •Вывод строки символов
- •Вывод на экран шестнадцатеричного числа
- •Процедуры
- •Ввод символов
- •Вывод на экран двоичного числа
- •Работа с дисковыми файлами
- •Префикс сегмента программы (psp)
- •Структура префикса программного сегмента.
- •Прерывания.
- •Табличные вызовы подпрограмм.
- •Макрокоманды.
- •Макроопределения.
- •Использование параметров в макроопределениях.
- •Директива local
- •Использование библиотек макроопределений.
- •Конкатенация. (&)
- •Директивы повторения.
- •Условные директивы.
- •Перечисление условных директив.
- •Пример использования ifnb.
- •Пример использования макроопределений.
- •Резидентные программы tsr (terminate and stay resident)
- •Защита резидентной программы от повторной загрузки.
- •Выгрузка резидентной программы.
- •Переключение стека в резидентной программе.
- •Обработчик прерываний от таймера
- •Контроллер прерываний и его программирование
- •Взаимодействие прикладных и системных обработчиков прерываний
- •Резидентный обработчик прерываний от клавиатуры с подключением до системного
- •Резидентный обработчик прерывания от клавиатуры с подключением после системного обработчика
- •Резидентный обработчик прерываний от клавиатуры с подключением как до, так и после системного.
- •Вывод на экран текста средствами bios
- •Режимы дисплея
- •Работа с видеобуфером.
- •Логическая организация текстового видеобуфера.
- •Программирование портов. Звук.
- •Программирование звукового канала таймера.
- •Интерфейс с Си
- •Программы с несколькими сегментами команд.
- •Программы с несколькими сегментами данных.
- •Директива assume. Инициализация сегментных регистров и замена сегментов.
- •Структуры и записи.
Переключение стека в резидентной программе.
При реализации процедуры прерывания (аппаратного или программного) процессор сохраняет в стеке прерванной задачи регистр флагов, сегментный регистр, регистр команд cs и указатель команд ip и загружает из вектора прерывания в регистры cs и ip двухсловный адрес обработчика прерывания. Все остальные регистры хранят эту информацию, которая в них была на момент прерывания. Для того, чтобы не разрушать прерванную задачу, в самом начале обработчика прерывания следует сохранить все используемые в обработчике регистры, а перед командой iret - восстановить их. Это относится к сегментным регистрам и к РОН. Все команды обращения к памяти используют по умолчанию в качестве сегментного регистра - регистр ds. Если при переходе в обработчик не выполнить настройку ds на сегмент обработчика, то команды вида:
mov ax, mem
mov bx,[si]
будут обращаться к случайным ячейкам прерванной задачи, что, возможно, приведет к разрушению и этой задачи, и обработчика. Если нежелательно перенастраивать регистр ds, то в командах работы с памятью следует использовать замену регистра:
mov ax,cs:mem
mov bx,cs:[si]
Особая ситуация возникает со стеком . При переходе в обработчик регистры ss и sp настроены на стек прерванной задачи. Если этот стек имеет достаточный объем, то обработчик его может использовать, а если нет - переполнение стека может привести к разрушению прерванной программы. Поэтому надежнее в обработчике прерывания иметь собственный стек. Если TSR программа «паразитирует» на чужом стеке, то в этом случае использование стека должно быть минимальным.
Смена стека требует запоминания кадра стека (содержимого ss и sp) в ячейках памяти отведенной обработчику, занесения в ss и sp новых значений и восстановления старого кадра перед выходом и обработчика. Естественно, что для стека должен быть выделен свободный объем (необходимый для запоминания своих данных, а может быть и чужих, от программ, «паразитирующих» на чужом стеке).
Если резидентная программа не допускает повторной активизации в процессе своей заботы, то можно не делать проверку переключения стека, и смена стека может быть осуществлена следующим образом:
org 100
start: jmp begin
ss_seg dw 0
ss_offs dw 0
mem dw 0
.
.
new_handler proc far
mov cs:ss_seg,ss ;сохранение кадра стека прерванной задачи
mov cs:ss_offs,sp
cli ;запрет прерываний
mov cs:mem,cs ;настроим ss на наш сегмент
mov ss,cs:mem
mov sp,offset end_res ;настроим sp
sti ;разрешим прерывания
; теперь работаем на стеке резидентной программы
.
.
.
;в конце резидентной части:
stack_area dw 256 dup (?)
new_handler endp
end_res=$
Процедура обработчика прерывания начинается с сохранения кадра стека прерванной задачи. Адресация ячеек выполняется через cs, поскольку ds еще указывает на сегмент данных вызвавшей программы. Установка нового кадра стека всегда выполняется при запрещенных прерываниях, т.к. если аппаратное прерывание произойдет между командами заполнения ss и sp, вектор прерванного процесса будет сохранен в случайной ячейки памяти. Заполнить сегментный стека можно и так:
push cs
pop ss
Однако это выполняется на стеке прерванной программы, приведенный же пример не затрагивает ни стека прерванной задачи, ни регистр ax, ни других регистров. Т.к. команда mov ss, cs запрещен, то содержимое cs копируется в ss через ячейку памяти mem. Команда mov sp, offset end_res заносит адрес для первого стека, место под которым выделено в самом конце резидентной чести обработчика. Под стек отведено 256 слов.
При запуске программы на выполнение DOS находит свободную область памяти подходящего размера. В начале программы создается префикс программного сегмента (PSP) размером в 256 байт. Сама программа загружается вслед за PSP. Кроме того, DOS передает программе копию среды. Размер среды от 160 байт для MS DOS 3.3 и выше. Сегментный адрес среды помещается в PSP по смещению 2ch. Резидентные программы практически никогда не используют среду DOS, занимаемую ею память можно освободить с помощью функции 49h.
mov es, word ptr ds:[2ch] ;загрузить сегментный адрес среды в es
mov ah, 49h ;и освободить память
int 21h
Резидентная программа не нуждается и в PSP. Младшая часть PSP (до смещения 5ch) используется DOS и в последний раз потребуется при выполнении функции 31h или прерывания 27h. В дальнейшем DOS будет использовать PSP прерванной программы.
Некоторые TSR программы используют PSP программы, например, пересылают резидентную часть программы в PSP c помощью команды movsb, уменьшая тем самым размер резидентной позиции. Однако, надежнее, проще и целесообразнее найти применение PSP в резидентной программе. Например, использовав его как буфер ввод-вывод или разместив в нем собственный стек. Последнее выполняется следующим образом:
вместо mov SP, offset end-res
mov SP, offset start
При этом получаем стек глубиной 256 бит или 128 слов, т.е. все PSP.