Программа Prg8 может быть активизирована горячей клавишей Alt-A как во время ожидания системой ввода символов в командную строку (обработчик new_28h), так и во время исполнения какой-либо задачи, использующей функции вывода DOS (обработчик таймера new_08h). Для исследования последней функции приведена тестовая программа Prg9.
Prg8. Резидентная программа, активизирующаяся нажатием клавиш Alt-A, выводит на экран системное время функцией DOS 40h с учётом анализа занятости DOS. Программа защищена от повторной установки и может быть выгружена командой с клавиатуры с опцией off.
IDEAL
MODEL tiny
P486N
CODESEG
org 100h
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
;Восстановим векторы 08h, 09h, 28h, 2Fh:
mov ax,2508h
…
;Получим из 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
;Чтение и сохранение векторов 08h, 09h, 28h, 2Fh:
mov ax,3508h ;AL=08h
int 21h
mov [word cs:old_08h],bx
mov [word cs:old_08h+2],es
…
;Установка векторов 08h 09h, 28h, 2Fh:
mov ax,2508h
mov dx, offset new_08h
int 21h
…
mov ah,09h
mov dx, offset msg1 ;Сообщение об успешной установке программы
int 21h
mov ax,3100h ;Завершим программу, оставив её
mov dx,(init-resident+10Fh)/16 ;резидентной в памяти
int 21h
Endp init
;Поля данных в нерезидентной части программы
msg1 db 'Резидентный обработчик установлен $'
msg2 db 'Попытка вторичной установки. Установка отменена $'
msg3 db 'Программа выгружена из памяти $'
option db 'off'
END resident ;Конец программы/точка входа
Prg9. Тестовая программа для исследования работы Prg8
;Программа использует функции DOS на стеке ввода/вывода в двух режимах.
;F1- режим попеременного вывода в бесконечном цикле двух строк функцией 09h в одно и то же
;место экрана. Смена символов в строке означает правильную её работу, F10- выход из режима и
;программы. F2- режим ввода c клавиатуры одиночных символов функцией 01h. F10- выход из
;режима и программы. Переход из одного режима в другой возможен через перезапуск программы.
Ideal
Model tiny
Codeseg
org 100h
Proc main
;Очистка экрана
mov ah,6 ;Функция инициализации окна или его очистка
mov al,0
mov bh,0Fh ;Атрибут; ярко-белый по чёрному
mov cx,0 ;Левый верхний угол
mov dx,184Fh ;Правый нижний угол
int 10h
;Выбор режима работы; F1- режим вывода строк, F2- режим ввода одиночных символов, F10-
;выход из программы
again: mov ah,08h ;Функция ввода одиночного символа без эха
int 21h ;Первый вызов DOS
cmp al,0 ;Расширенный ASCII код?
jne again ;Нет
mov ah,08h ;Да, введём старший байт
int 21h ;Повторный вызов DOS
cmp al,3Bh ;Нажата F1?
je F1 ;Да
cmp al,3Ch ;Нажата F2?
je F2 ;Да
jmp again ;Нажато незапланированное
;Попеременный вывод в бесконечном цикле двух строк на одно и то же место экрана. Смена
;символов в строке означает правильную работу. F10 –выход из программы
;Установим позицию курсора функцией BIOS 02h
F1: mov ah,02h ;Функция BIOS установки курсора
mov bh,0 ;Страница
mov dh,05h ;Строка (из 25)
mov dl,0h ;Столбец (из 80)
int 10h
;Цикл вывода
continual_1: mov ah,09h ;Вывод первой строки
mov dx, offset str1
int 21h
call check_cycle ;Проверка условия нахождения в цикле вывода
jnc F10 ;CF=0, Выходим из цикла
call delay ;Задержка
mov ah,09h ;Вывод второй строки
mov dx, offset str2
int 21h
call check_cycle ;Проверка условия нахождения в цикле вывода
jnc F10 ;CF=0, выходим из цикла
call delay ;Задержка
jmp continual_1 ;Продолжим
;Процедура задержки delay
Proc delay
mov cx,1000
L2: push cx
xor cx, cx
L1: loop L1 ;Внутренний цикл задержки
pop cx
loop L2 ;Внешний цикл задержки
ret
Endp delay
;Процедура проверки условий продолжения цикла. Если CF=1 - продолжаем, при CF=0 - выходим
;(была нажата клавиша F10)
Proc check_cycle
mov ah,06h ;Функция ввода. Если функция обнаружила в буфере
;клавиатуры символ, то возвращает ZF=0 и в AL код символа. В противном случае устанавливает
;ZF=1 и продолжает программу
mov dl,0FFh ;Режим ввода
int 21h
jnz M1 ;ZF=0, произведём анализ введённого символа
M2: stc ;Установим CF=1, как признак продолжения цикла
jmp ex1
M1: cmp al,0 ;Расширенный ASCII-код
jne M2 ;Нет, продолжим текущий цикл
mov ah,06h ;Введём второй байт
mov dl,0FFh ;Режим ввода
int 21h
cmp al,44h ;Клавиша F10?
jne M2 ;Нет, продолжим текущий цикл
clc ;CF=0, признак выхода из цикла
ex1: ret
Endp check_cycle
;Цикл ввода одиночных символов функцией DOS 01h. Выход из программы – F10.
;Установим позицию курсора функцией BIOS 02h
F2: mov ah,02h ;Функция BIOS установки курсора
mov bh,0 ;Страница
mov dh,07h ;Строка (из 25)
mov dl,0h ;Столбец (из 80)
int 10h
;Ввод с клавиатуры одиночных символов функцией DOS 01h с эхом
continual_2: mov ah,01h
int 21h
cmp al,0 ;Расширенный ASCII-код?
jne continual_2 ;Нет, повторим ввод
mov ah,08h ;Повторный вызов функции DOS для ввода
int 21h ;старшего байта
cmp al,44h ;F10?
jne continual_2 ;Нет, продолжим цикл
F10: mov ax,4C00h ;Выход в DOS
int 21h
Endp main
;Поля данных вывода
str1 DB 40 DUP('*'),13,'$'
str2 DB 40 DUP('&'),13,'$'
End main ;Конец программы/точка входа
Комментарий к исследованию резидентной программы Prq8. При взведённом флаге требования на обработку task_request (функция аппаратного обработчика 09h, активизируемого клавишной комбинацией Alt-A) исполнение процедуры task по выводу времени на экран монитора осуществляется:
¨ Прикладным обработчиком new_28h, когда компьютер не занят исполнением никакой программы и управление передано командному процессору .
¨ Прикладным обработчиком таймера new_08h – в первом режиме работы тестовой задачи, посвящённом попеременному выводу строк на экран функцией DOS 09h.
¨ Прикладным обработчиком new_28h – во втором режиме работы тестовой задачи при вводе одиночных символов с клавиатуры функцией DOS 01h.
12. Межпрограммные коммуникации
Здесь будут рассмотрены важные вопросы обмена информацией (данными) между резидентом и некоторой транзитной программой, образующими единый программный комплекс с заранее установленными соглашениями взаимодействия (интерфейсом) друг с другом. В виду важности рассматриваемых вопросов, разработаем для этого специальный программный комплекс, посвящённый реализации некоторой вычислительной процедуре над числами, вводящимися оператором с клавиатуры.
Определим пока функции программ комплекса для решения поставленной задачи в следующем виде:
Транзитная программа, проверив наличия резидента в памяти, – вводит исходные числа в числовые буфера собственной памяти данных с последующим преобразованием их в двоичный дополнительный код. Подготовленные для вычислений данные передаются в поля данных резидента, после чего транзитная программа переходит в режим активного ожидания, выполняя вывод на экран какой-либо мерцающий символ типа вращающегося курсора.
Резидент, активизируемый специальными «горячими клавишами» клавиатуры, в период выполнения транзитной программой процедуры активного ожидания, производит заданные вычисления, сообщая об их окончании транзитной программе.
Транзитная программа считывает результат из памяти данных резидента в свой сегмент данных, преобразует их к виду, соответствующим требованиям к выводу на экран, и выполняет данный вывод.
Ясно, что в процессе взаимодействия, программы комплекса могут (или должны) обмениваться дополнительными осведомительными сигналами, регламентирующими их действия в процессе решения общей задачи.
12.1. Формы передачи данных между программами комплекса
12.1.1 Передача данных через регистры и стек
В случае если резидент активизируется по программному прерыванию, то наиболее естественный способ передачи данных (параметров) осуществляется через регистры или, что более предпочтительно, через стек (резидент, как известно, при синхронной активизации работает на стеке вызвавшей его программы). При этом данные формы передачи практически ничем не отличаются от аналогичных способов передачи параметров между программой и процедурой дальнего типа. На первый взгляд, передача параметров через стек в нашем программном комплексе не актуальна, так как резидент активизируется асинхронно. Аппаратное прерывание может прервать транзитную программу тогда, когда, допустим, выполнялась какая-либо функция DOS, и в этом случае пара регистров SS:SP будет настроена на один из собственных стеков DOS. Однако, если резидент комплекса использует мультиплексное прерывание 2Fh, то процесс передачи параметров и его активизация может быть разделён. Через прерывание 2Fh мы (в синхронном режиме) можем осуществить не только передачу параметров через стек, но и некоторый флаг, разрешающий с этого момента резиденту выполнять проверку нажимаемых клавиш с целью отыскания «горячих», обнаружение которых и позволит ему перейти к выполнению вычислительной процедуры.
Обозначим программу резидента как Tsr, а транзитную программу комплекса – Transit, тогда соответствующие участки программ, могут выглядеть следующим образом.
Программа Transit.exe:
……………….
;Проверим наличие резидента в памяти
mov ax, 0C800h ;Функция 0C8h, подфункция проверки наличия копии
;резидента в памяти 00h
int 2Fh ;
cmp al,0FFh ;Вернулся код 0FFh?
jne no1 Нет, на выход. Нужно установить резидент
;Да, резидент с заданной функцией 0С0h установлен. Выведем
;соответствующее сообщение и продолжим работу
…………………..
;Выполним загрузку параметров в стек для их последующей передачи резиденту
push [a1] ;Параметр а1
push [a2] ;Параметр а2
push [result] ;Параметр result (очевидно, пока он пуст или заполнен
;каким–либо спецсимволом)
push [fl_active] ;Значение fl_active=1, переводящее обработчик
;клавиатурного прерывания new_09h в активное состояние
push ds ;Адрес сегмента данных программы transit. Может
;понадобится для передачи результата, вычисленного резидентом, а так же каких-либо признаков,
;характеризующих корректность (или нет) выполненных вычислений, в сегмент данных программы
;transit
mov ax, 0C803h ;Функция 0C8h с подфункцией загрузки параметров 03h
int 2Fh ;мультиплексного прерывания int 2Fh
;Мы можем так отстроить диалог, чтобы получать подтверждение выполнения своих
;инструкций! Желательно также восстановить состояние стека
……………………
exit: mov ax,4C00h
int 21h
no1:
;Вывод сообщения об отсутствии резидента в памяти
……………………
jmp exit
Программа Tsr.com, включающая обработчики new_09h и new_2Fh, а так же инсталляционную часть резидента в памяти.
…………………….
;Для простоты будем считать, что переменные в полях данных резидента являются одноимёнными с переменными программы transit
…………………….
Proc new_2Fh
;Прикладной мультиплексный обработчик прерывания new_2Fh. Назначение:
;- функции защиты от повторной загрузки и выгрузки из памяти,
;- межпрограммный интерфейс в информационном взаимодействии с транзитной программой
cmp ah,0C8h ;Наша функция?
jne out_2Fh ;Не наша, на выход
cmp al,00h ;Подфункция проверки на повторную установку
je iamhere ;Да, сообщим о невозможности повторной установки
cmp al,01h ;Подфункция выгрузки?
je uninst ;Да, на выгрузку
cmp al,03h ;Подфункции загрузки параметров резидента
je loading ;Да, переход на загрузку
jmp short out_2Fh ;Неизвестная подфункция, на выход
;Загрузка полей данных резидента параметрами из программы transit
loading: push bp ;Сохраним bp с целью последующей адресации стека через него
mov bp, sp
;------
;Структура стека после команды push bp
; bp bp+0
; ip bp+2
; cs bp+4
; fl bp+6
; ds bp+8
; [fl_active] bp+10
; [result] bp+12
; [a2] bp+14
; [a1] bp+16
;
mov bx,[bp+10] ;
mov [fl_active],bx
mov bx,[bp+12] ;
mov [result],bx
mov bx,[bp+14] ;
mov [a2],bx ;
mov bx,[bp+16] ;
mov [a1],bx
mov bx,[bp+8] ;
mov [SegData_transit],bx
pop bp
iamhere: mov al,0FFh
iret
out_2Fh: jmp [dword cs:old_2Fh] ;Переход в следующий по цепочке обработчик прерывания 2Fh
…………………………….
uninst:
…………………………….
iret
Endp new_2Fh
……………...
12.1.2. Передача данных через область межзадачных связей BIOS
Область межзадачных связей (ОМС) BIOS объёмом 16 байт расположена в адресном пространстве 40h:F0h … 40h:FFh. Эта область не используется DOS и предназначена специально для межпрограммных коммуникаций пользовательских программ. Учитывая, что данная область имеет небольшой объём, обмен через неё осуществляется, как правило, с помощью передачи адресов. Запись и считывание данных в область межзадачных связей BIOS требует предварительной настройки регистра es
……………………………..
pop es
mov ax,40h
mov es, ax
;Поместим теперь в ОМС, например, по адресу 40h:0F0h, сегментный адрес данных транзитной программы
mov [word es:0F0h],ds
;Или адрес переменной X1
lea ax,[X1]
mov [word es:0F2h],ax
…………………………….
Дальнейшие пояснения использования ОМС в рассматриваемых задачах, очевидно не требуется.
12.1.3. Передача данных из транзитной программы непосредственно в поля данных
резидента
Предполагается, что транзитная программа в течение своего исполнения владеет полным адресом Segment:Offset полей данных резидента. Данный способ мне представляется наиболее удобным и эффективным. В дальнейшем предполагается, что резидент выполнен в формате .COM.
q Резидент с сигнатурой.
Считается, что поля данных резидента непосредственно примыкают к пользовательскому вектору new_09h. Транзитная программа в начале своей работы проверяет наличие резидента в памяти, запрашивая адрес данного обработчика с помощью функции 35h, прерывания int 21h. Тем самым, становится известным полный адрес нижней границы полей данных резидента, где обычно и располагается сигнатура (см. Prg6. Шаблон резидента с сигнатурой). Считывая значение сигнатуры и, сравнивая её со значением, установленным программным соглашением, транзитная программа, в случае совпадения, заносит в свою память полный адрес нижней границы поля данных резидента. Дальнейшее конструирование программ комплекса исходит из следующего условия: резиденту доступны переменные только из собственного поля данных, транзитной программе - как переменные резидента, так, естественно, и свои собственные. Хотя, конечно, транзитная программа (если очень надо) может передать резиденту собственный сегментный адрес данных.
q Резидент с мультиплексным прерыванием 2Fh.
Коммуникативные возможности между программами комплекса здесь значительно шире, так как (это уже отмечалось выше) в данном случае транзитная программа всегда может обратиться к резиденту в синхронном режиме через посредство прерывания 2Fh. Ниже приводится один из возможных шаблонов построения комплекса, учитывающий наиболее значимые требования, предъявляемые к программам подобного типа. Переменные полей данных, команды и процедуры программы, снабжены подробыми комментариями, что позволит пользователям без особых затруднений наполнить шаблон реальным содержанием под конкретную вычислительную процедуру. Чтобы уйти от проблемы нереентерабельности DOS, транзитная программа trans_m. exe в процедуре ожидания Waiting использует вывод на экран способом непосредственного программирования памяти.
Обратите внимание, что предложенный в данном программном комплексе способ проверки нахождения резидента в памяти использует дополнительный отличительный признак (маркер) для используемой в программе функции 0C8h прерывания int 2Fh, возвращаемый в регистре dx!
Наличие данных шаблонов совсем не преследует цель лишить разработчиков индивидуальных подходов в построении программного комплекса. Наоборот, рассматривайте это как базу или подспорье, для создания более интересных программ.
%TITLE ""
Comment /* Резидентный обработчик , работающий в паре с транзитной программой trans_m. exe выполняет вычислительную процедуру Calc “……”. Активизируется горячими клавишами Alt-A, если предварительно транзитная программа установила флаг активности fl_active в "1". Межпрограммный интерфейс (обнаружение себя в памяти и передача параметров в комплексе) основан на мультиплексном прерывании 2Fh. */
IDEAL
MODEL tiny
p486n
Codeseg
org 100h
proc resident
jmp init
;Данные резидентной части программы и место для перехватываемых векторов
old_09h dd 0
old_2FH dd 0
mes db 'Процедура Calc вызвана нажатием горячих клавиш Alt-A'
meslen = $-mes
;Числовые двоичные буфера
arg_1 DW 0 ;Аргумент_1
arg_2 DW 0 ;Аргумент_2
res_1 DW 0 ;Результат_1
res_2 DW 0 ;Результат_2
state DB 0FFh ;Переменная-состояние, характеризующая корректность
;выполненных вычислений процедурой Calc. Устанавливается резидентом в состояние 0 (корректно) :или 1(не корректно) по окончании вычислений
fl_active db 0 ;Флаг активности fl_active резидента, разрешающий
;прикладному обработчику клавиатуры new_09h отфильтровывать "горячие клавиши" Alt-A. При их
;обнаружении, запускается на исполнение вычислительная процедура Calc. Флаг устанавливается в ;"1" транзитной программой, сбрасывается в "0" резидентом в момент вызова процедуры Calc
;------
Proc new_2Fh
;Прикладной мультиплексный обработчик прерывания new_2Fh. Назначение:
;- функции защиты от повторной загрузки и выгрузки из памяти,
;- межпрограммный интерфейс в информационном взаимодействии с транзитной программой
cmp ah,0C8h ;Наша функция?
jne out_2Fh ;Не наша, на выход
cmp al,00h ;Подфункция проверки на повторную установку
je iamhere ;Да, сообщим о невозможности повторной установки
cmp al,01h ;Подфункция выгрузки?
je uninst ;Да, на выгрузку
cmp al,02h ;Подфункция загрузки адреса точки входа резидента
je address
jmp short out_2Fh ;Неизвестная подфункция, на выход
iamhere: mov al,0ffh
mov dx,12F3h ;Загрузка дополнительного признака идентификации – маркера
;функции 0С8h прерывания 2Fh
jmp L_iret
;Адрес точки входа в резидентную часть
address: mov bx, offset new_2Fh ;Смещение
mov cx, cs ;Сегмент
L_iret: iret
out_2Fh: jmp [dword cs:old_2Fh] ;Переход в следующий по цепочке обработчик прерывания 2Fh
;Выгрузим программу из памяти, предварительно восстановив все перехваченные ею векторы
uninst: push ds
……………………………
iret
Endp new_2Fh
;Прикладной обработчик клавиатурного прерывания new_09h.
;Устанавливается в активное состояние транзитной программой флагом fl_active=1. В активном
;состоянии отфильтровывает горячие клавиши Alt-A. После обнаружения горячих клавиш сбрасывает
:флаг активности fl_active в "0" и запускает на выполнение вычислительную процедуру Calc.
Proc new_09h ;Новый обработчик прерывания 09h
pusha ;Сохраним регистры
push ds es
mov ax, cs
mov ds, ax ;ds=cs
cmp [fl_active],1 ;Производить проверку кодов нажатия клавиш?
je @@work ;Да
jmp @@Exit ;Нет
@@work: ;Отфильтровываем комбинацию Alt-A
in al,60h ;Читаем из порта данных клавиатуры скан-код клавиши
cmp al,1Eh ;Если это [А], то работаем дальше
jz @@ok
@@Exit:
pop es ds
popa
jmp [dword cs:old_09h] ;В системный обработчик прерывания без возврата
@@ok:
mov ax,40h
mov es, ax
mov al,[es:17h] ;Получим первый байт флагов состояния клавиатуры
test al,08h ;Клавиша Alt нажата?
je @@Exit ;Нет, перейдём в системный обработчик
sti ;Разрешим аппаратные прерывания
mov [fl_active],0 ;Запретим дальнейшую проверку нажатия клавиш
call Calc ;Вызов процедуры Calc при ds=cs и es=40h
cli ;Запретим аппаратные прерывания
in al,61h ;Разрешим дальнейшую работу контроллеру клавиатуры
or al,80h
out 61h, al
and al,7fh
out 61h, al
mov al,20h ;Пошлём в контроллер команду EOI
out 20h, al
pop es ds ;Восстановим регистры и выйдем из прерывания
popa
iret
Endp new_09h
;------
;Краткая харатеристика вычислительной процедуры Calc, входные и выходные данные.
Proc Calc
;Загрузка операндов в регистры
push es
push ds
pop es ;es=ds
mov ax,[arg_1]
mov bx,[arg_2]
; ………………..
;Реализации вычислений может предшествовать проверка знаков полученных чисел или их величина,
;значения которых позволит получить корректный результат.
;Результаты вычислений по заданному алгоритму, а также их корректность заносятся в переменные
;res_1, res_2, и state, находящиеся в поле данных резидента.
; ………………..
;Вывод сообщения на экран о выполнениии процедуры Calc функцией 13h, прерывания BIOS int 10h
; ………………..
Endp Calc
;------
Endp resident
Proc init
;Секция инициализации
;- Выполняется проверка на наличие в памяти первого экземпляра резидента.
;- Если первый экземпляр не обнаружен, то независимо от вида запускающей программу команды
;(с хвостом или без него), происходит переход на метку ОК с установкой программы в памяти
;- При обнаружении первого экземпляра программы начинается сравнение хвоста программы с
;ожидаемым
;- Если результат сравнения оказался отрицательным (хвост есть, но другой), программа завершается ;выводом сообщения о невозможности повторной установки
;- При идентичности хвоста ожидаемому, резидент выгружается из памяти с выводом соответствую-
;щего сообщения
mov ax,0C800h ;Запрос на наличие в памяти первого
int 2Fh ;экземпляра программы
cmp al,0ffh ;Вернулся код 0ffh?
jne ok ;Нет, данная программа в памяти отсутствует
;Выполним её установку, перейдя на метку оk
cmp dx,12F3h ;Наша функция 0С8h имеет дополнительный сравни-
;тельный признак - возвращаемое регистром dx значение должно быть равно данному значению
jne anothers ;Функция 0C8h используется другими программами
;Первый экземпляр обнаружен. Был ли у команды хвост 'off'?
…………………….
exit: mov ax,4C00h ;Функция DOS 4Сh:выход из программы
int 21h ;Вызов DOS. Останов
anothers: mov dx, offset msg4
mov ah,09h
int 21h
jmp exit
ok: ;Копии резидента в памяти нет. Установим программу
…………………………
mov dx, offset msg1 ;Сообщение об успешной установке программы
int 21h
mov ax,3100h ;Завершим программу, оставив её резидентной в памяти
mov dx,(init-resident+10Fh)/16
int 21h
Endp init
;Поля данных в нерезидентной части программы
msg1 db 'Резидентный обработчик установлен $'
msg2 db 'Попытка вторичной установки. Установка отменена $'
msg3 db 'Программа выгружена из памяти $'
msg4 db 'Функция 0C8h прерывания 2Fh не свободна $'
command db 'off'
End resident ;Конец программы/точка входа
%TITLE "trans_m. exe"
Comment /*Транзитная программа trans_m. asm, образующая совместно с резидентом программный комплекс для выполнения вычислительной процедуры Calc. Межпрограммный интерфейс (обнаружение резидента и передача параметров) осуществляется через прерывание int 2Fh */
IDEAL
MODEL small
p486n
STACK 256
%NOMACS
MACRO out_str$ mes ;Макрос вывода ASCII$ строки
…………………….
ENDM out_str$
MACRO out_buf buf, number ;Макрос вывода ASCII-символов из буфера buf
…………………….
ENDM out_buf
DATASEG
;Сообщения интерактива, отражающие особенности ввода десятичных чисел, а также взаимодействие
;с резидентом
mes1 DB 13,10,’Введите …………arg_1………………………………….…….$'
mes2 DB 13,10,’Введите………….arg_2………………………………………..$'
err1 DB 13,10,'Ошибка ввода: переполнение или недопустимый символ $'
mes_noinst1 DB 13,10,'Резидент не был загружен! $'
mes_noinst2 DB 13,10,'В памяти установлен резидент с функцией 0C8h,'
DB ' прерывания 2Fh, но другой сигнатурой.'
DB 13,10,'Внесите изменения в программы и переустановите резидент $'
mes_inst DB 13,10,'Резидент загружен, продолжим работу $'
mes_err2 DB 13,10,'Процедура Calc не была вызвана – нажмите Alt-A $'
mes_err3 DB 13,10,'Результат не может быть получен $'
mes3 DB 13,10,'Результат_1: $'
mes4 DB 13,10,'Результат_2: $'
mes5 DB 13,10,'Продолжим работу <F1>, или выйдем <F10>? $'
;Числовые ASCII-буфера ввода/вывода
Input db 7,?,7 dup (?) ;Входной буфер десятичной ASCII-строки (знак+5цифр+CR)
Output db 6 dup (?) ;Выходной буфер десятичной ASCII-строки (знак+5цифр)
;Поля данных процедуры Waiting
mes6 db 13,10,'Режим ожидания (вращающийся курсор) нажатия клавиш:'
db 13,10,'комбинация Alt-A - приказ резиденту выполнить процедуру'
db 13,10,'Esc - выход из ожидания',13,10,'$'
sprite db '|/–\|/–\' ;Вращающийся курсор
pos dw?
;Двоичные числовые буфера
arg_1 DW 0 ;Аргумент_1
arg_2 DW 0 ;Аргумент_2
res_1 DW 0 ;Результат_1
res_2 DW 0 ;Результат_2
state DB 0FFh ;Переменная-состояние, характеризующая корректность
;выполнения процедуры Calc. Устанавливается резидентом по окончании вычислений.
;Адрес точки входа в резидент
tsr_off dw?
tsr_seg dw?
CODESEG
Start: mov ax,@data ;Установка в ds адреса
mov ds, ax ;сегмента данных
;Проверим наличие резидента в памяти с функцией 0C8h прерывания 2Fh и маркером 12F3h
xor dx, dx
mov ax,0C800h ;Запрос на наличие в памяти резидента
int 2Fh
cmp al,0FFh ;Вернулся код 0FFh?
jne no1 ;Нет, на выход. Нужно установить резидент
;Да, резидент с функцией 0C8h прерывания 2Fh установлен. Тогда регистр dx должен содержать
;маркер 12F3h?
cmp dx,12F3h ;Маркеры совпали?
jne no2 ;Нет, Нужно сменить функцию для прерывания 2Fh
out_str$ mes_inst ;Маркеры совпали. Резидент с заданной функцией 0С8h
;и маркером 12F3h установлен. Выведем соответствующее сообщение
;Получим адрес точки входа резидента
xor bx, bx
xor cx, cx
mov ax,0C802h ;Запрос на загрузку адреса точки входа резидента
int 2Fh
;Запишем адрес точки входа резидента в соответствие с установленными соглашениями
mov [tsr_off],bx ;Offset
mov [tsr_seg],cx ;Segment
;Продолжим работу
begin:
;Последовательно выполняется в режиме интерактива для каждого аргумента:
;– ввод десятичного числа во входной буфер Input
;– преобразованием его в двоичный дополнительный код
;– запись двоичного кода в соответствующий числовой буфер
……………………
;Выполним загрузку полей данных резидента
mov bx,[tsr_off] ;Восстановим адрес точки входа
mov es,[tsr_seg]
again: push bx es
mov ax,[arg_1] ;Занесём по порядку
mov [es:bx-10],ax
…………………
mov al,[state]
mov [es:bx-2],al
;Установим флаг активности fl_active резидента, разрешающий прикладному обработчику
;клавиатуры new_09h фильтровать "горячие клавиши" Alt-A
mov [byte es:bx-1],1
;Перейдём к процедуре ожидания (заглушке) Waiting, реализующей в бесконечном цикле вывод на
;экран вращающего курсора. Нажатие Alt-A приведёт к выполнению резидентом вычислительной
;процедуры Calc. Выход из процедуры ожидания, - нажатие клавиши Esc
call Waiting
pop es bx
;Загрузка числовых буферов программы данными, полученными от резидента
mov ax,[es:bx-6]
mov [res_1],ax
mov ax,[es:bx-4]
mov [res_2],ax
mov al,[es:bx-2]
mov [state],al
push bx es
;Проверка флага корректности вычислений и вывод соответствующих сообщений для случаев б) и в):
;а) state=0 - ОК,
;б) state=1 - полученные резидентом данные не корректные,
;в) state=0FFh - вычислительная процедура Calc не была вызвана (не была нажата комбинация Alt-A).
……………………..
Out_str$ mes_err3 ;Вычисления выполнены не корректно
Jmp dialog
no_ok: Out_str$ mes_err2 ;Процедура не была вызвана
pop es bx
jmp again ;Во время выполнения процедуры Waiting не была нажата
;комбинация Alt-A
……………………...
Ok: ;Вывод результатов вычислений резидента на экран.
Mov ax,[res_1]
;Если результат res_1 в формате “byte”, то выполните
;mov al,[res_1]
;cbw
;Последовательно выполняется для каждого результата:
;– преобразование двоичного дополнительного кода «результата_i» в десятичную ASCII - строку c
;записью в буфер Output (call Bin_ASCIIdec)
;– вывод соотстветствующего сообщения и «результата_i» из буфера Output на экран
out_str$ mes3
out_buf Output,6
……………………..
Mov [state],0FFh ;Сброс флага состояния state в исходное состояние
;Блок управления программой. Продолжение работы – клавиша <F1>, выход - <F10>.
dialog: pop es bx ;status quo "push-pop"
out_str$ mes5
……………………..
Exit: mov ax,4C00h ;Функция DOS 4Сh:выход из программы
int 21h ;Вызов DOS. Останов
no1: out_str$ mes_noinst1
jmp short Exit
no2: out_str$ mes_noinst2
jmp short Exit
;
;П/программа ввода в буфер Input 6-разрядного (5 раз. + знак) десятичного числа в ASCII-кодах
;старшими разрядами вперёд с предварительным вводом знака '-' для отрицательных числа. После
;ввода производится преобразование данного числа в двоичный 16-битовый дополнительный код.
;Ограничитель диапазона вводимых чисел в регистре SI:
;SI=32767 для диапазона -32768...32767
;SI=127 для диапазона -128...127
;По возвращению двоичное число находится в АХ, а признак ошибки преобразования во флаге CF.
;Значение CF=1 фиксирует либо выход 10-ричного числа из заданного диапазона, либо ввод
;ошибочного символа.
Proc ASCIIdec_bin
call IN_NUM ;Процедура ввода десятичного числа в буфер IN_NUM
call ASCIIdec_binary ; Процедура преобразование числа из буфера IN_NUM в
;двоичный 16-битовый дополнительный код.
ret
Endp ASCIIdec_bin
………………..
;
;Процедура ожидания (заглушка) Waiting, реализующая в бесконечном цикле вывод на экран
;вращающегося курсора. Производится фильтрация нажатия клавиш:
;Резидентом - комбинация Alt-A - приказ на выполнение процедуру вычисления,
;Программой trans_m - клавиша Esc - выход из процедуры Waiting.
Proc Waiting
out_str$ mes6 ;Вывод подсказки
;Получим позицию курсора, используя функцию 03h прерывания int 10h
……………………
;Вывод на экран спрайта анимации (вращающийся курсор) путём непосредственного программиро-
;ования памяти. Преобразуем координаты курсора из системы "строка - столбец" в номер пиксела
;(рег. ах) на экране монитора
……………………
;Настроим пару es:di на адрес вывода
push es
……………………
mov si,0 ;Индекс считывания элементов Sprite
;Вывод в цикле текущего символа строки sprite
@@loop: mov dh,14h ;красный по синему
mov dl,[sprite+si] ;очередной символ
mov [es:di],dx ;вывод на экран
inc si
and si,07h ;Цикл вывода включает все элементы Sprite
call delay ;Временная задержка
;Проверка буфера клавиатуры без ожидания (функция 01h, int 16h) на наличие в нём символа. При
;проверке, возвращаемая в АХ информация не удаляется из буфера: ZF=1- буфер пуст, ZF=0-
;в буфере есть сисмволы
mov ah,01h
int 16h
jz short @@loop ;Символ отсутствует
mov ah,00h ;Чтение символа клавиатуры в АХ (скан-код и ASCII-код) с
int 16h ; с удалением из буфера. Ожидаем, если буфер пуст
cmp al,1Bh ;Нажата Esc?
je short @@end ;Да, на выход
jmp short @@loop ;Нет, продолжим вывод анимации
@@end: pop es
ret
Endp Waiting
;Процедура delay многократно повторяется, поэтому используем локальные метки
proc delay
………………………..
ret
Endp delay
;---
;Процедура Bin_ASCIIdec преобразования 16-разрядного дополнительного кода двоичного числа в
;ASCII - cтроку 10-ричных цифр (знак+5цифр).
;Вход: Рег. АХ - дополнительный код двоичного числа
;Выход: Рег. АХ - дополнительный код двоичного числа
;Буфер Output, с преобразованным из рег. АХ десятичным числом.
Proc Bin_ASCIIdec
…………………………
ret
Endp Bin_ASCIIdec
;
End Start ;Конец программы/точка входа
13. Индивидуальные задания на проектирование
1 – 10 варианты.
Индивидуальные особенности первых десяти вариантов определяются видом вычислительной процедуры Calc, которая представляет собой различные варианты реализации сложных арифметических операций, рассмотренных в лабараторной работе «Программирование алгоритмов сложных арифметических операций»[5]
1. Беззнаковое умножение в формате 16х16 (рис. 10.2).
2. Знаковое умножение по способу 1 в формате 16х16 (рис. 10.2).
3. Знаковое умножение по способу 2 в формате 16х16 (рис. 10.4).
4. Знаковое умножение по способу 3 в формате 16х16 (рис.10.5).
5. Двоичное знаковое умножение 32-битовых сомножителей на основе команды беззнакового умножения Mul для 16- битовых слов (рис.10.6).
6. Беззнаковое деление в формате 32:16 (рис 10.8).
7. Знаковое деление в формате 32:16 (рис.10.10).
8. Знаковое деление четырёхсловного делимого на однословный делитель на основе использования штатной команды процессора div src (формат 64:16=64).
9. Извлечение квадратного корня из 32- битового числа (рассмотреть два из наиболее распространённых алгоритмов).
10. Знаковое умножение многоразрядных неупакованных BCD-чисел в формате NxM=N+M-1, где N и M- число десятичных разрядов, включая знаковый разряд.
Параграф §12 настоящего руководства по курсовому проекту как раз и посвящён реализации резидента с одной из указанных процедур.
Вычислительная процедура и алгоритмические особенности её реализации должна быть представлены в виде подпрограммы в специальном разделе проекта:
· Описание алгоритма;
· Программный модуль с использованием тех обозначений переменных и имён регистров, которые используются при рассмотреннии модели алгоритма;
· Отладка модуля с использованием Turbo Debuggera и результаты отладки ( см. пункт 10.14 лабараторной работы «Программирование алгоритмов сложных арифметических операций»).
11. Резидент-замедлитель исполнения программ. Замедление реализуется поцедурой задержки, вставленной в обработчик прерывания пользователя по таймеру (int 1Ch). Инициализация резидента осуществляется через посредство комбинации клавиш <Scroll Lock+Цифровая клавиша>. Значение символа цифровой клавиши влияет на скорость замедления. Рекомендуемая литература [Л. 3, 8]
12. Резидент, выводящий на экран квадрат типа красной дыры. Программа перехватывает прерывание int 1Ch и постоянно подменяет атрибуты символов внутри квадрата. Программа действует только в режиме экрана 3, поэтому вначале проверяется режим экрана. Вывод на экран (подмена атрибутов) реализуется путём непосредственного программирования памяти. Предусмотреть дрейф дыры по экрану в какую-либо сторону с восстановлением прежних аттрибутов.
13. Разработать прикладной резидентный обработчик прерывания new_04h, вызывающий прерывание тестовой задачи (с выводом соответствующего сообщения) при возникновении переполнения в операциях сложения и вычитания.
14. Разработать тестовую задачу с прикладным обработчиком new_09h, осуществляющего вывод на экран (после каждого нажатия произвольной клавиши) содержимого порта 60h контроллера клавиатуры, слово статуса флагов клавиатуры и первых 4-х байтов кольцевого буфера клавиатуры. Выход из программы по истечению обработки 40 клавиш. Рекомендуемая литература [Л. 9]
15. Разработать резидентную программу с прикладным обработчиком клавиатуры new_09h. Программа осуществляет вывод на экран код нажатия и отпускания для произвольной клавиши. Выход из программы по истечению обработки 40 клавиш. Рекомендуемая литература [Л. 9]
16. Разработать резидентную программу с прикладным обработчиком new_09h от клавиатуры. Программа осуществляет вывод на экран скан-код и ASCII - код для произвольной клавиши. Выход из программы по истечению обработки 40 клавиш.
17. Разработать резидентную программу динамического дампа регистров общего назначения, активизируемую через вектор 03h. Содержимое регистров выводится на экран в 16-теричном коде. Демонстрацию программы провести на основе одной из ваших программ лабораторного практикума. Рекомендуемая литература [Л. 8]
18. Разработать резидентную программу динамического дампа сегментных регистров регистра флагов и программного счётчика, активизируемую через вектор 03h. Содержимое регистров выводится на экран в 16-теричном коде. Демонстрацию программы провести на основе одной из ваших программ лабораторного практикума. Рекомендуемая литература [Л. 8].
19. Разработать резидентную программу динамического дампа памяти данных тестовой задачи. Вывод данных осуществляется в формате Turbo Debugger, соответствующем команде внутреннего меню окна дампа Alt+F10 > Display as > Byte. Резидент активизируется через пользовательский вектор.
20. Разработать прикладной обработчик new_01h пошагового выполнения (трассировки) программы. Содержательная часть обработчика должна выводить на экран содержимое всех регистров РОН после исполнения каждой команды для той части программы, для которой флаг TF=1. Покомандное исполнение реализуется клавишей F8. Демонстрацию программы провести на основе одной из ваших программ лабораторного практикума. Рекомендуемая литература [Л. 2]
При написании программы и её демонстрации обратите внимание на тот факт, что некоторые команды не вызывают прерывание int 1h. Такими командами являются cli, pushf, int, into, int 3, iret и popf, а также команды, следующие за командами загрузки сегментных регистров.
21. Разработать прикладной обработчик new_01h пошагового выполнения программы. Содержательная часть обработчика должна выводить на экран содержимое дампа памяти в формате Turbo Debugger после исполнения каждой команды для той части программы, для которой флаг TF=1. Покомандное исполнение реализуется клавишей F8. Демонстрацию программы провести на основе одной из ваших программ лабораторного практикума. Рекомендуемая литература [Л. 2]
22. Некоторая тестовая задача выводит на экран текущее время из КМОП – часов (функция 02h int 1Ah) и, добавляя к нему 20 секунд, устанавливает будильник (функция 06h int 1Ah). Срабатывание будильника активизирует резидентную программу (обработчик 4Ah), которая выводит на экран приветственное сообщение и короткий звонок (одноголосая мелодия). Рекомендуемая литература [Л. 2]
23. Некоторая тестовая задача выводит на экран текущее время из КМОП – часов и, добавляя к нему 10 секунд, устанавливает будильник. Срабатывание будильника активизирует резидентную программу, которая воспроизводит фрагмент мелодичного перезвона (последовательность сигналов для нот какой-либо октавы). Рекомендуемая литература [Л. 3, 8]
24. Разработать резидентную программу, выводящую на экран монитора (правый верхний угол) текущее время из КМОП – часов с интервалом в 1 сек. Каждый вывод времени вызывается активизацией прикладного обработчика от будильника new_4Ah. Вывод производится способом прямой записи в видеопамять. Рекомендуемая литература [Л. 3, 8]
25. Резидент, заменяющий комбинацию клавиш Ctrl+Alt+Del для перезагрузки компьютера, на комбинацию Ctrl+Alt+R_Shift+Del [Л. 10,11]
14. Требования к оформлению и содержанию курсовой работы.
1. Курсовая работа должна иметь титульный лист и состоять из 12 – 15 листов печатного текста шрифтом, равный 12 пунктам.
2. Содержание КР включает следующие обязательные параграфы (разделы):
· Задание.
· Структура программы и обоснование выбора её отдельных модулей (составных обработчиков прерываний) должна учитывать следующие факторы:
– Вычислительные процедуры, используемые в программе, должны соответствовать заданному алгоритму реализации;
– Резидентная программы должна обязательно включать прикладной обработчик клавиатурного прерывания Int new_09h, быть защищенной от повторной установки, обладать способностью самовыгрузки из памяти;
– Прикладной аппаратный обработчик прерываний должны строится с учётом свойства нереентерабельности DOS;
– Программа должна работать с хорошо продуманным экранным интерфейсом.
· Справочное описание используемых в программе системных обработчиков, сервисных функций DOS и BIOS.
· Функциональное описание программы и результаты её демонстрации.
· Листинги программ.
3. Необходимые компьютерные файлы на дискете для демонстрации программы.
15. Литература,
1. Финогенов по системным функциям MS-DOS.- Изд.2,-М.: Радио и связь, Энтроп, 1995.-382 с., илл.
2. Освоение Turbo Assembler. - Киев: Диалектика,19с., ил.
3. Финогенов языка Ассемблера. - М.: Радио и связь, 19с.: ил.
4. Assembler. Для DOS, Windows и Unix.-М.: ДМК, 1999с., ил.
5. Assembler /В. Юров. - СПб: Издательство «Питер», 20с.: ил.
6. Assembler: Специальный справочник. СПб: Питер, 2000.
7. Assembler. Учебный курс. - М.: "Нолидж", 2001.-848с.
8. Финогенов ассемблера: уроки программирования. - М.: ДИАЛОГ-МИФИ, 20с.
9. Программирование на аппаратном уровне. Специальный справочник. СПб: Питер, 2001.
10. Ирвин Кип. Язык ассемблера для процессоров Intel, 3-е издание. :Пер. с англ.– М.: «Вильямс», 2002. – 616 с.
11. Питер Абель. Ассемблер. Язык программирования для IBM PC: пер. с англ.- К.:Век+, М,: ЭНТРОП, 200с.
12. Assembler IBM PC: Учебное пособие. Лабораторный практикум. - Новосибирск: Изд-во НГТУ, 2003. – 115с.
13. Cайт кафедры ВТ НГТУ: http:/ermak. cs. *****/asm-pc/
¨ Учебно методический комплекс к лабораторному практикуму по языку Assembler IBM PC.
Методический материал к выполнению курсовой работы подготовил доцент
кафедры ВТ НГТУ .
Редакция - декабрь, 2004г.
[1] Если прикладной обработчик new_09h содержит внутри себя собственную процедуру обработки информации, (например, с именем task) то перед выполнением данной процедуры необходимо позаботиться о разрешении прерываний для таймера, «оконтурив» процедуру task командами sti и cli.
[2]Перед запуском тестовой программы проверьте, имеется ли у вас строка в файле config.nt:
device=c:\winnt\system32\ansi. sys
или что-нибудь подобное, отражающее путь в вашем компьютере к драйверу MS-DOS - ANSI. SYS
[3]Для просмотра окружения программы загрузите её в отладчик Turbo Debugger, откройте окно CPU, перейдите в окно дампа памяти и с помощью команды Goto в открывшемся окне установите адрес DS:002Ch. В окне дампа по этому адресу откроется содержимое PSP, начиная с адреса 2Сh. Запомни те значение сегментного адреса (обозначим его SegSetting), записанного по указанному выше адресу и, вновь воспользовавшись командой Goto, установите адрес SegSetting:0000h.
[4]В программе FAR, написанной с использованием API - функций Windows, а не функций DOS, разрушение системы не произойдёт
[5] Файл MultiDiv. doс из предложенного учебно-методического пакета “Assembler”
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 |


