Методическое руководство к курсовой работе по дисциплине Assembler ibm pc содержание

Вид материалаРуководство

Содержание


Proc resident ;Основная процедура
Proc new_08h
Подобный материал:
1   2   3   4   5   6   7   8   9
^

Proc resident ;Основная процедура


jmp init ;Переход на инициализацию

;Данные резидентной части программы и место для хранения перехватываемых векторов

old_08h dd 0

old_09h dd 0

old_28h dd 0

old_2Fh dd 0

in_dos dd 0 ;Двухсловный адрес занятости DOS InDOS

task_request db 0 ;Флаг требования обработки

string db '***'

time db '00:00:00' ;Формат вывода времени

db '***'

str_len = $-string

ten db 10 ;Делитель

consol db 'CON',0 ;Имя консоли в формате файловых функций
^

Proc new_08h


;Прикладной обработчик таймера new_08h – как активизатор процедуры task резидентной части

;программы

pusha ;Сохраним все регистры, в том числе сегментные!

push ds

push es

pushf ;Перейдём в системный обработчик

call [dword cs:old_08h] ;с возвратом

cmp [cs:task_request],1 ;Процедура task требует запуска

jne out_08h ;Нет, можно завершить обработку

les bx,[cs:in_dos] ;Выясним, свободна ли DOS? Для этого

;занесём адрес флага в ES:BX

cmp [byte es:bx],0 ;DOS свободна?

jne out_08h ;Нет, придётся подождать

cmp [byte es:bx-1],0 ;DOS свободна, а как с флагом ErrorMode?

jne out_08h ;DOS находится в режиме обработки

;критической ошибки, придётся подождать

dec [cs:task_request] ;Оба флага занятости DOS="0", сбросим

;флаг требования на обработку

call task ;Запустим процедуру обработки task

out_08h: pop es ;Восстановим регистры

pop ds

popa

iret ;Завершим обработчик

Endp new_08h

Proc new_09h

;Прикладной обработчик клавиатуры new_09h, устанавливающий флаг требования обработки

;task_request при нажатии комбинации клавиш Alt-A

pusha ;Сохраним регистры

push es

in al,60h ;Введём скан-код

cmp al,1Eh ;Скан-код клавиши А?

je go ;Да, на продолжение анализа

exit1: pop es ;Восстановим регистры

popa

jmp [dword cs:old_09h] ;В системный обработчик без возврата

go: mov ax,40h ;Настроим ES на сегмент данных BIOS

mov es,ax

mov al,[es:17h] ;Получим первый байт флагов

test al,08h ;Клавиша Alt нажата?

jne hotkey ;Да, выявлена комбинация Alt-A

jmp exit1 ;Нет, перейдём в системный обработчик

hotkey: inc [cs:task_request] ;Установим флаг требования обработки

;Разрешим дальнейшую работу клавиатуры

in al,61h ;Ввод содержимого порта 61h



;Пошлём в контроллер обработки прерываний команду EOI



;Восстановим регистры и выйдем из прерывания

pop es

popa

iret ;Возврат в прерванную программу

Endp new_09h

Proc new_28h

;Обработчик прерывания new_28h, активизирующей выполнение процедуры task во время исполне-

;ния функций DOS ввода с клавиатуры. Данный обработчик может инициировать процедуру с ис-

;пользованием функций DOS дисковой группы. Файловая функция вывода 40h будет использо-

;ваться с нестандартными дескрипторами клавиатуры

pusha ;Сохраним регистры, в том числе сегментные!

push ds

push es

cmp [cs:task_request],1 ;Процедура task требует запуска

jne out_28h ;Нет, можно завершить обработку

les bx,[cs:in_dos] ;Выясним, свободна ли DOS? Для этого занесём адрес флага

;занятости в ES:BX. Адрес флага критической ошибки ErrorMode будет находиться в ES:BX-1

cmp [byte es:bx-1],0 ;Флаг ErrorMode сброшен?

jne out_08h ;Нет, придётся подождать

cmp [byte es:bx],1 ;Флаг InDOS больше 1?

ja out_28h ;Да, на выход. Режим вложенных вызовов запрещён

dec [cs:task_request] ;Нет, сбросим флаг требования на обработку

call task ;Запустим процедуру обработки task

out_28h: pop es ;Восстановим регистры

pop ds

popa

iret ;Завершим обработчик

Endp new_28h

Proc task

;Процедура, активизируемая горячей клавишей Alt-A и использующей файловую функцию Dos 40h

;для вывода системного времени на экран

pusha

push ds

;Получим системное время (двоичный код) с помощью функции DOS 2Ch

mov ah,2Ch ;Возврат: CH- часы, CL- минуты, DH- секунды

int 21h

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

;несением в строку time

mov al,ch ;Часы

lea bx,[cs:time] ;Адрес позиции в строке

call bin_decasc ;Преобразуем в десятичные символы



;Вывод на экран функцией DOS 40h через нестандартный дескриптор. Сохраним позицию курсора с

;помощью функции BIOS 03h.

mov ah,03h

mov bh,0

int 10h ;DH:DL- строка и столбец текущей позиции курсора

push dx ;Сохраним DH:DL

;Установим позицию курсора функцией BIOS 02h

mov ah,02h ;Функция BIOS установки курсора

mov bh,0 ;Страница

mov dh,10h ;Строка (из 25)

mov dl,10h Столбец (из 80)

int 10h

push cs

pop ds ;ds=cs

mov ah,3Dh ;Функция открытия файла с доступом для записи.

mov al,1 ;Возвращает в ах дескриптор для последующих операций над файлом

mov dx,offset consol ;Адрес имени файла в DS:DX

int 21h ;Дескриптор в ах

mov bx,ax ;Перешлём дескриптор в bx

mov ah,40h ;Файловая функция вывода DOS 40h

mov cx, str_len

mov dx,offset string ;Адрес буфера в DS:DX

int 21h

;Восстановим позицию курсора

mov ah,02h ;Функция BIOS установки курсора

mov bh,0

pop dx ;DX=DH:DL- сохранённая позиция курсора

int 10h

pop ds ;Восстановим регистры

popa

ret

Endp task

Proc bin_decasc

;Процедура преобразования 8-разрядного двоичного кода в двухразрядный десятичный ASCII- фор-

;мат. Вход: al-двоичный код, BX- адрес записи десятичного ASCII- числа



ret

Endp bin_decasc

Proc new_2Fh

;Прикладной мультиплексный обработчик прерывания new_2Fh

cmp ah,0C8h ;Наша функция?



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

uninst: push ds

push es

push dx

mov ax,2508h ;Восстановим вектор 08h



mov ax,2509h Восстановим вектор 09h



mov ax,2528h ;Восстановим вектор 28h



mov ax,252Fh ;Восстановим вектор 2Fh

;Получим из PSP адрес собственного окружения и выгрузим его



;Выгрузим теперь программу из памяти вместе с PSP

iret

Endp new_2Fh

Endp resident

Proc init

;Секция инициализации

;- Выполняется проверка на наличие в памяти первого экземпляра резидента.

;- Если первый экземпляр не обнаружен, то независимо от вида запускающей программу команды

;(с хвостом или без него) происходит переход на метку ОК с установкой программы в памяти

;- При обнаружении первого экземпляра программы начинается сравнение хвоста программы с

;ожидаемым

;- Если результат сравнения оказался отрицательным (хвост есть, но другой), программа завершается

;выводом сообщения о невозможности повторной установки

;- При идентичности хвоста ожидаемому, резидент выгружается из памяти с выводом

;соответствующего сообщения



;Копии резидента в памяти нет. Установим программу

;Получение адреса флагов занятости InDOS и ErrorMode

ok: mov ah,34h ;Получим адрес флага InDOS (косвенно ErrorMode)

int 21h

mov [word cs:in_dos],bx ;offset ErrorMode=[bx-1]

mov [word cs:in_dos+2],es

mov ax,3508h ;Чтение и сохранение вектора 08h



mov ax,3509h ;Чтение и сохранение вектора 09h



mov ax,3528h ;Чтение и сохранение вектора 28h



mov ax,352Fh ;Чтение и сохранение вектора 2Fh



mov ax,2508h ;Установка обработчика 08h

mov dx,offset new_08h

int 21h

mov ax,2509h ;Установка обработчика 09h



mov ax,2528h ;Установка обработчика 28h



mov ax,252Fh ;Установка обработчика 2Fh



mov ah,09h

mov dx,offset msg1 ;Сообщение об успешной установке программы

int 21h

mov ax,3100h ;Завершим программу, оставив её

mov dx,(init-resident+10Fh)/16 ;резидентной в памяти

int 21h