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

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

Содержание


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

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


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

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

old_09h dd 0

old_2Fh dd 0

string db '***'

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

db '***' ;’$’

strlen = $-string

ten db 10

;Прикладной обработчик клавиатуры new_09h, анализирующий скан-коды клавиш. Все коды, кроме

;кода 4Еh (сер. плюс) передаются в системный обработчик. Нажатие клавиши "сер. плюс" приводит

;к выдаче конца прерывания EOI и вызову процедуры получения системного времени DOS 2Ch.

;Время выводится на экран с использованием средств BIOS
^

Proc new_09h


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

push es

push ds

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

cmp al,4Eh ;Скан-код серого плюса

je hotkey ;Да, на активизацию резидента

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

pop es

popa

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

hotkey: sti ;Разрешим аппаратные прерывания с более высоким приоритетом,

;(в данном случае таймеру).

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

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

mov ah,2Ch

int 21h

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

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

mov al,ch ;Часы

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

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

mov al,cl ;Минуты

lea bx,[cs:time+3]

call bin_decasc

mov al,dh ;Секунды

lea bx,[cs:time+6]

call bin_decasc

;***

;Выведем время на экран функцией BIOS 13h, в режиме 0. После записи курсор принимает исходное

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

;Так как адрес буфера строки для функции 13h задаётся значением ES:BP, установим ES=CS

push cs

pop es

mov ah,13h ;Функция BIOS 13h

mov al,0 ;Режим 0. Строка содержит только коды символов

mov bh,0 ;0- страница

mov bl,0Ch ;Розовый по чёрному

mov cx,strlen

mov dh,10 ;Номер строки (из 25)

mov dl,25 ;Номер столбца (из 80)

mov bp,offset string ;Поместим адрес буфера в ES:BP

int 10h ;Прерывание BIOS

;***

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

cli ;Запретим аппаратные прерывания

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

or al,80h ;Подтвердим приём кода, добавив "1" к

out 61h,al ;старшему разряду байта

and al,7Fh ;Снова разрешим работу клавиатуры,

out 61h,al ;сбросив старший бит в порте 61h

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

mov al,20h

out 20h,al

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

pop ds

pop es

popa

iret

Proc bin_decasc

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

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

xor ah,ah

div [cs:ten] ;al=quot ax/10, ah=rem ax/10

add al,'0' ;Преобразуем в ASCII- символ старший разряд

mov [cs:bx],al ;Запись старшего разряда

add ah,'0'

mov [cs:bx+1],ah ;Запись младшего разряда, образованного остатком от деления

ret

Endp bin_decasc

Endp new_09h

Proc new_2Fh

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

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

jne out_2Fh ;Не наша, - на выход

cmp al,00h ;Подфункция проверки на повторную установку

je i_here ;Да, сообщим о невозможности повторной установки

cmp al,01h ;Подфункция выгрузки?

je uninst ;Да, на выгрузку

jmp short out_2Fh ;Неизвестная подфункция, на выход

i_here: mov al,0ffh

iret

out_2Fh: jmp [dword cs:old_2Fh] ;Переход в следующий по цепочке обработчик

;прерывания 2Fh

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

uninst: push ds

push es

push dx

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

lds dx,[cs:old_09h]

int 21h

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

lds dx,[cs:old_2Fh]

int 21h

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

mov es,[cs:2Ch] ;es <- сегментный адрес окружения программы

mov ah,49h ;Функция освобождения блока памяти

int 21h

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

push cs

pop es ;es снова указывает на начало PSP

mov ah,49h ;Функция освобождения блока памяти

int 21h

pop dx

pop es

pop ds

iret

Endp new_2Fh

Endp resident

Proc init

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

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

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

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

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

;ожидаемой

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

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

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

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

mov ax,0C800h ;Запрос на наличие в памяти первого

int 2Fh ;экземпляра программы

cmp al,0ffh ;Вернулся код 0ffh?

jne ok ;Нет, данная программа в памяти отсутствует. Выполним её

;установку, перейдя на метку оk

;Первый экземпляр обнаружен. Была ли у команды опция 'off'?

mov cl,[es:80h] ;Получим длину хвоста из PSP

cmp cl,0 ;Длина хвоста = 0?

je fin ;Да, программа запущена без него

xor ch,ch ;Пусть сх=cl=длина хвоста

mov di,81h ;Адрес хвоста es:di в PSP

mov al,' ' ;Уберём пробелы из начала хвоста

repe scasb ;Сканируем хвост (al - dst), пока пробелы

dec di ;di- первый символ после пробела

mov cx,3 ;Ожидаемая длина опции

mov si,offset option ;Адрес ожидаемой опции (option) ds:si

repe cmpsb ;Сравниваем введённую опцию с ожидаемой

jne fin ;Опции не совпали. На выход

mov ax,0C801h ;Опции совпали, пошлём в резидентную

int 2Fh ;программу команду (al=01) на выгрузку. По окончанию

mov dx,offset msg3 ;выгрузки выведем сообщение об этом

jmp fin1

fin: mov dx,offset msg2 ;Попытка вторичной установки

fin1: mov ah,09h

int 21h

mov ax,04C00h ;Функция DOS 4Сh: выход из программы

int 21h ;Вызов DOS. Останов

;Первой экземпляр (резидент) отсутствует. Установим программу

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

int 21h

mov [word cs:old_09h],bx

mov [word cs:old_09h+2],es

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

int 21h

mov [word cs:old_2Fh],bx

mov [word cs:old_2Fh+2],es

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

mov dx,offset new_09h

int 21h

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

mov dx,offset new_2Fh

int 21h

mov ah,09h

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

int 21h

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

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

int 21h