
Int 10h
shl dx,1
loop out2
In al, 61h
or AL, 80h ;В регистр по адр. 61h
out 61h, AL ;засылаем 1 в 7-й разряд
and AL, 7Fh ;В регистр по адр. 61h
out 61h, AL ;засылаем 0 в 7-й разряд
mov AL, 20h ;В регистр по адр. 20h
out 20h, AL ;засылаем 1 в 5-й разряд
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop AX
Iret ; возврат из прерывания
old_2F dd 0
old_09 dd 0
s_byte db 'Byte statusa klaviatury $'
;-------------------------------------- Инициирующая часть
M1:
mov cl, es: 80h ; Чтение командной строки
cmp cl,0 ; и поиск символа '/'
jz no
mov al,'/'
mov di, 81h
mov ch, 0
repne scasb
CMP byte ptr [DI], 'r'
je M3
mov si,offset se_
cmpsb
je set
no: mov ah,09h ; Если не найдено, вывод сообщения
mov dx, offset s_no_param
Int 21h
mov ax,4c00h ; и выход
int 21h
set:
mov AH,0C8h ;Вызовем INT 2Fh с функцией 0C8h
mov AL,00 ;и подфункцией 00h
int 2Fh
cmp AL,0FFh ;Вернулась подфункция = FFh?
jne ok ;Eсли 'нет', то устанавливаем программу
jmp already ;Если да то вывод сообщения и выход
ok:
mov AX,352Fh ;Получим в ES:BX старый адрес
int 21h ;обработчика прерывания int 2Fh
mov word ptr CS:old_2F,BX ;и запомним его
mov word ptr CS:old_2F+2,ES ;в ячейке old_2F
mov AX,252Fh Установим новый адрес
lea DX,M4 ;обработчика прерывания int 2Fh
int 21h
MOV AX, 3509h
INT 21h
MOV word ptr CS:old_09,BX
MOV word ptr CS:old_09+2,ES
MOV AX,2509h
LEA DX, M2
INT 21h
MOV AH,09h
LEA DX, mess
INT 21h
MOV AX, 3100h
MOV DX, (M1-BYT +10Fh)/16
INT 21h
;-----------------------Вызов выгрузки РП
M3:
MOV AH,0C8h
MOV AL, 01
INT 2Fh
MOV AH,09h
LEA DX ,mess2
INT 21h
MOV AX, 4C00h
INT 21h
already: ;Программа уже загружена в оперативную память
mov AH,09h ;Выведем строку:
lea DX, s_yes_inst ;'Программа уже установлена'
int 21h
mov AX,4C00h ;Завершим без установки
int 21h ;pезидентной программы
;----------------------------------------------------------------------------
s_no_param db 'Net parametra$'
se_ db 'add'
unse_ db 'r'
s_yes_inst db 10,13, 'Programma uge zagrugena$'
mess db 'rezid proga zagrugena$'
mess2 db 'Rezid proga udalena$'
SEG1 ENDS
END BYT
Вывод:
При запуске программы с клавиатуры используются опции(ключи загрузки-выгрузки)
PROGA /z - загрузить в память резидентную программу
PROGA /v - выгрузить из памяти резидентную программу
Программа вызывается по прерыванию от таймера пользователя (возникает 18,2 раз в сек) с вектором 1Ch. Это дублер прерывания системного таймера IRQ0.
Для того, чтобы прикладные программы могли использовать сигналы таймера,
не нарушая при этом работу системных часов, в программу BIOS, обслуживающую
аппаратные прерывания от таймера, поступающие через вектор 08, включен вызов
int 1Ch, передающий управление на программу-заглушку BIOS, которая содержит
единственную команду iret .Пользователь может записать в вектор
1Ch адрес прикладного обработчика сигналов таймера и использовать в своей
программе средства реального времени.
В нашем случае программа выводит в нижний правый угол экрана показания системных часов в ответ на каждый 64-й запрос таймера
Для снижения частоты вывода
нам пришлось в обработчике отсчитывать прерывания и выводить символ на экран
не при каждом вызове обработчика, а на каждый 64-й вызов.
В обработчике предусматривается ячейка count для отсчета прерываний. При
каждой активизации обработчика содержимое этой ячейки увеличивается на 1
Для выделения каждого 64-ого запуска обработчика в
программе используется команда test.
Команда test byte ptr CS:count,3Fh в сочетании с командой jnz M3
осуществляет переход на метку M3 т.е. на завершение программы, если
установлен хотя бы один из битов 0 ..5 байта count. Таким образом,
содержательная часть обработчика будет выполняться лишь в тех случаях, когда
все эти биты сброшены. При последовательном наращивании счетчика count такая
ситуация будет возникать при каждом 64-ом вызове обработчика. Следует
обратить внимание на необходимость использования в рассматриваемой команде
описателя byte ptr (byte pointer, указатель на байт). При указании второго
операнда в виде "безразмерного" непосредственного значения транслятор не
может решить, анализировать ли ему байт или слово.
Для управления процессом выгрузки воспользуемся мультиплексным
прерыванием INT 2Fh.
Обработчик прерывания INT 2Fh резидентной программы должен:
- приняв прерывание, проверить номер функции в регистре AH и, если
номер не свой, передать управление ранее загруженной резидентной
программе, также использующей прерывание INT 2Fh
JMP CS:old_2f
здесь 'old_2f' - ячейка памяти, где хранится старый адрес вектора
прерывания INT 2Fh.
- если номер функции свой, проверить номер подфункции в регистре AL
и, выполнив необходимые действия (в нашем случае это выгрузка
резидентной программы из памяти), вернуться в вызвавшую программу
командой IRET.
Если программа запущена с параметром в виде
PROGA/v
выполняется выгрузка резидентной программы из памяти.
Для выгрузки программы из памяти, внутри резидентной части есть специальная
программа выгрузки(строки15-45).
А для вызова программы выгрузки, в инициализирующей части используем прерывание
INT 2Fh.
В результате выполнения курсовой работы, была разработана РП на языке ассемблера персональных компьютеров типа IBM PC, работающих под управлением операционной системы MS-DOS в реальном режиме.
РП выводит показания системных часов в нижний правый угол экрана с частотой – один
раз в 3-4сек , что соответствует каждому 64-ому запросу таймера.
Ключ загрузки - /z. Ключ выгрузки - /v
Литература:
1. П.И.Рудаков, К.И.Финогенов "Программируем на языке ассемблера
IBM PC", Часть 1. Основы. Москва, изд. "Энтроп", 1995 г.
2. П.И.Рудаков, К.И.Финогенов "Программируем на языке ассемблера
IBM PC", Часть 2. Прикладное программирование. Москва, изд. "Энтроп",
1995 г.
3. Питер Абель “АССЕМБЛЕР язык и программирование для IBM PC”
4.О. Калашников “АССЕМБЛЕР? ЭТО ПРОСТО”