Перехват прерываний
Перехват прерываний в работе процессора во время выполнении текущей программы. Типы и особенности развития данных ситуаций. Практические примеры обработчика программного прерывания. Определение значения нескольких векторов, установление нового значения.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | контрольная работа |
Язык | русский |
Дата добавления | 13.08.2011 |
Размер файла | 81,9 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
; чтобы получить адрес атрибута,
; а не символа
mov al, 071h; атрибут - синий на сером
stosb; вывод на экран
ret
display_all endp
int09h_handler endp; конец обработчика INT 09h
; буфер для хранения содержимого части экрана, которая накрывается нашим окном
screen_buffer db 1190 dup(?)
; первая строка окна
display_line1 db 0DAh, 11 dup (0C4h), '* ASCII *', 11 dup (0C4h), 0BFh
; последняя строка окна
display_line2 db 0C0h, 11 dup (0C4h), '* Hex '
hex_byte1 db?; старшая цифра текущего байта
hex_byte2 db?; младшая цифра текущего байта
db ' *', 10 dup (0C4h), 0D9h
hw_reset2D: retf; ISP: минимальный hw_reset
; обработчик прерывания INT 2Dh
; поддерживает функции AMIS 3.6 00h, 02h, 03h, 04h и 05h
int2Dh_handler proc far
jmp short actual_int2Dh_handler; ISP: пропустить блок
old_int2Dh dd?; ISP: старый обработчик
dw 424Bh; ISP: сигнатура
db 00h; ISP: программное прерывание
jmp short hw_reset2D; ISP: ближний jmp на hw_reset
db 7 dup (0); ISP: зарезервировано
actual_int2Dh_handler:; начало собственно обработчика INT 2Dh
db 80h, 0FCh; начало команды CMP АН, число
mux_id db; идентификатор программы
je its_us; если вызывают с чужим АН - это не нас
jmp dword ptr cs:old_int2Dh
its_us:
cmp al, 06; функции 06h и выше
jae int2D_no; не поддерживаются
cbw; AX = номер функции
mov di, ax; DI = номер функции
shl di, 1; умножить его на 2, так как jumptable -
; таблица слов
jmp word ptr cs:jumptable[di]; косвенный переход на обработчики
; функций
jumptable dw offset int2D_00, offset int2D_no
dw offset int2D_02, offset int2D_03
dw offset int2D_04, offset int2D_05
int2D_00:; проверка наличия
mov al, 0FFh; этот номер занят
mov сх, 0100h; номер версии 1.0
push cs
pop dx; DX:DI - адрес AMIS-сигнатуры
mov di, offset amis_sign
iret
int2D_no:; неподдерживаемая функция
mov al, 00h; функция не поддерживается
iret
int2D_02:; выгрузка программы
mov byte ptr cs:disable_point, 0CFh; записать код команды IRET
; по адресу disable_point
; в обработчик INT 09h
mov al, 04h; программа дезактивирована, но сама
; выгрузиться не может
mov bx, cs; BX - сегментный адрес программы
iret
int2D_03:; запрос на активизацию для «всплывающих» программ
cmp byte ptr we_are_active, 0; если окно уже на экране,
je already_popup
call save_screen; сохранить область экрана,
push cs
pop ds
call display_all; вывести окно
mov byte ptr we_are_active, 1; и поднять флаг
already_popup:
mov al, 03h; код 03: программа активизирована
iret
int2D_04:; получить список перехваченных прерываний
mov dx, cs; список в DX:BX
mov bx, offset amis_hooklist
iret
int2D_05:; получить список «горячих» клавиш
mov al, 0FFh; функция поддерживается
mov dx, cs; список в DX:BX
mov bx, offset amis_hotkeys
iret
int2Dh_handler endp
; AMIS: сигнатура для резидентных программ
amis_sign db «Cubbi…»; 8 байт - имя автора
db «ASCII…»; 8 байт - имя программы
db «ASCII display and input utility», 0; ASCIZ-комментарий
; не более 64 байт
; AMIS: список перехваченных прерываний
amis_hooklist db 09h
dw offset int09h_handler
db 2Dh
dw offset int2Dh_handler
; AMIS: список «горячих» клавиш
amis_hotkeys db 01h; клавиши проверяются после стандартного
; обработчика INT 09h
db 1; число клавиш
db 1Eh; скан-код клавиши (А)
dw 08h; требуемые флаги (любая Alt)
dw 0; запрещенные флаги
db 1; клавиша глотается
; конец резидентной части
; начало процедуры инициализации
initialize proc near
mov ah, 9
mov dx, offset usage; вывести информацию о программе
int 21h
; проверить, не установлена ли уже наша программа
mov ah, - 1; сканирование номеров от FFh до 00h
more_mux:
mov al, 00h; Функция 00h - проверка наличия программы
int 2Dh; мультиплексорное прерывание AMIS,
cmp al, 00h; если идентификатор свободен,
jne not_free
mov byte ptr mux_id, ah; записать его номер прямо в код
; обработчика int 2Dh,
jmp short next_mux
not_free:
mov es, dx; иначе - ES:DI = адрес их сигнатуры
mov si, offset amis_sign; DS:SI = адрес нашей сигнатуры
mov cx, 16; сравнить первые 16 байт,
repe cmpsb
jcxz already_loaded; если они не совпадают,
next_mux:
dec ah; перейти к следующему идентификатору,
jnz more_mux; пока это не 0
; (на самом деле в этом примере сканирование происходит от FFh до 01h,
; так как 0 мы используем в качестве признака отсутствия свободного
; номера в следующей строке)
free_mux_found:
cmp byte ptr mux_id, 0; если мы ничего не записали,
je no_more_mux; идентификаторы кончились
mov ax, 352Dh; АН = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 2Dh
mov word ptr old_int2Dh, bx; и поместить его в old_int2Dh
mov word ptr old_int2Dh+2, es
mov ax, 3509h; AH = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 09h
mov word ptr old_int09h, bx; и поместить его в old_int09h
mov word ptr old_int09h+2, es
mov ax, 252Dh; AH = 25h, AL = номер прерывания
mov dx, offset int2Dh_handler; DS:DX - адрес нашего
int 21h; обработчика
mov ax, 2509h; AH = 25h, AL = номер прерывания
mov dx, offset int09h_handler; DS:DX - адрес нашего
int 21h; обработчика
mov ah, 49h; AH = 49h
mov es, word ptr envseg; ES = сегментный адрес среды DOS
int 21h; освободить память
mov ah, 9
mov dx, offset installed_msg; вывод строки об успешной
int 21h; инсталляции
mov dx, offset initialize; DX - адрес первого байта за
; концом резидентной части
int 27h; завершить выполнение, оставшись
; резидентом
; сюда передается управление, если наша программа обнаружена в памяти
already_loaded:
mov ah, 9; АН = 09h
mov dx, offset already_msg; вывести сообщение об ошибке
int 21h
ret; и завершиться нормально
; сюда передается управление, если все 255 функций мультиплексора заняты
; резидентными программами
no_more_mux:
mov ah, 9
mov dx, offset no_more_mux_msg
int 21h
ret
; текст, который выдает программа при запуске:
usage db «ASCII display and input program»
db «v1.0», 0Dh, 0Ah
db «Alt-A - активация», 0Dh, 0Ah
db «Стрелки - выбор символа», 0Dh, 0Ah
db «Enter - ввод символа», 0Dh, 0Ah
db «Escape - выход», 0Dh, 0Ah
db «$»
; текст, который выдает программа, если она уже загружена:
already_msg db «Ошибка: программа уже загружена», 0Dh, 0Ah, '$'
; текст, который выдает программа, если все функции мультиплексора заняты:
no_more_mux_msg db «Ошибка: Слишком много резидентных программ»
db 0Dh, 0Ah, '$'
; текст, который выдает программа при успешной установке:
installed_msg db «Программа загружена в память», 0Dh, 0Ah, '$'
initialize endp
end start
Резидентная часть этой программы занимает в памяти целых 2064 байта (из которых на собственно коды команд приходится только 436). Это вполне терпимо, учитывая, что обычно программа типа ascii.com запускается перед простыми текстовыми редакторами для DOS (edit, multiedit, встроенные редакторы оболочек типа Norton Commander и т.д.), которые не требуют для своей работы полностью свободной памяти. В других случаях, как, например, при создании программы, копирующей изображение с экрана в файл, может оказаться, что на счету каждый байт; такие программы часто применяют для сохранения изображений из компьютерных игр, которые задействуют все ресурсы компьютера по максимуму. Здесь резидентным программам приходится размещать данные, а иногда и часть кода, в старших областях памяти, пользуясь спецификациями HMA, UMB, EMS или XMS.
Выгрузка резидентной программы из памяти
Чтобы выгрузить резидентную программу из памяти, необходимо сделать три вещи: закрыть открытые программой файлы и устройства, восстановить все перехваченные векторы прерываний, и наконец, освободить всю занятую программой память. Трудность может вызвать второй шаг, так как после нашего резидента могли быть загружены другие программы, перехватившие те же прерывания. Если в такой ситуации восстановить вектор прерывания в значение, которое он имел до загрузки нашего резидента, программы, загруженные позже, не будут получать управление. Более того, они не будут получать управление только по тем прерываниям, которые у них совпали с прерываниями, перехваченными нашей программой, в то время как другие векторы прерываний будут все еще указывать на их обработчики, что почти наверняка приведет к ошибкам. Поэтому, если хоть один вектор прерывания не указывает на наш обработчик, выгружать резидентную программу нельзя. Это всегда было главным вопросом, и спецификации AMIS и IBM ISP (см. предыдущую главу) являются возможным решением этой проблемы. Если вектор прерывания не указывает на нас, имеет смысл проверить, не указывает ли он на ISP-блок (первые два байта должны быть EBh 10h, а байты 6 и 7 - «K» и «B»), и, если это так, взять в качестве вектора значение из этого блока и т.д. Кроме того, программы могут изменять порядок, в котором обработчики одного и того же прерывания вызывают друг друга.
Последний шаг в выгрузке программы - освобождение памяти - можно выполнить вручную, вызывая функцию DOS 49h на каждый блок памяти, который программа выделяла через функцию 48h, на блок с окружением DOS, если он не освобождался при загрузке, и наконец, на саму программу. Однако есть способ заставить DOS сделать все это (а также закрыть открытые файлы и вернуть код возврата) автоматически, вызвав функцию 4Ch, объявив резидент текущим процессом. Посмотрим, как это делается на примере резидентной программы, занимающей много места в памяти. Кроме того, этот пример реализует все приемы, использующиеся для вызова функций DOS из обработчиков аппаратных прерываний, о которых рассказано в главе 5.8.3.
; scrgrb.asm
; Резидентная программа, сохраняющая изображение с экрана в файл.
; Поддерживается только видеорежим 13h (320x200x256) и только один файл.
; HCI:
; Нажатие Alt-G создает файл scrgrb.bmp в текущем каталоге с изображением,
; находившимся на экране в момент нажатия клавиши.
; Запуск с командной строкой /u выгружает программу из памяти
; API:
; Программа занимает первую свободную функцию прерывания 2Dh (кроме нуля)
; в соответствии со спецификацией AMIS 3.6
; Поддерживаемые подфункции AMIS: 00h, 02h, 03h, 04h, 05h
; Все обработчики прерываний построены в соответствии с IBM ISP
; Резидентная часть занимает в памяти 1056 байт, если присутствует EMS,
; и 66 160 байт, если EMS не обнаружен
model tiny
code
186; для сдвигов и команд pusha/popa
org 2Ch
envseg dw?; сегментный адрес окружения
org 80h
cmd_len db?; длина командной строки
cmd_line db?; командная строка
org 100h; COM-программа
start:
jmp initialize; переход на инициализирующую часть
; Обработчик прерывания 09h (IRQ1)
int09h_handler proc far
jmp short actual_int09h_handler; пропустить ISP
old_int09h dd?
dw 424Bh
db 00h
jmp short hw_reset
db 7 dup (0)
actual_int09h_handler:; начало собственно обработчика INT 09h
pushf
call dword ptr cs:old_int09h; сначала вызвать старый
; обработчик, чтобы он завершил аппаратное
; прерывание и передал код в буфер
pusha; это аппаратное прерывание - надо
push ds; сохранить все регистры
push es
push 0040h
pop ds; DS = сегментный адрес области данных BIOS
mov di, word ptr ds:001Ah; адрес головы буфера
; клавиатуры,
cmp di, word ptr ds:001Ch; если он равен адресу
; хвоста,
je exit_09h_handler; буфер пуст, и нам делать нечего,
mov ax, word ptr [di]; иначе: считать символ,
cmp ah, 22h; если это не G (скан-код 22h),
jne exit_09h_handler; выйти
mov al, byte ptr ds:0017h; байт состояния клавиатуры,
test al, 08h; если Alt не нажата,
jz exit_09h_handler; выйти,
mov word ptr ds:001Ch, di; иначе: установить адреса головы
; и хвоста буфера равными, то есть
; опустошить его
call do_grab; подготовить BMP-файл с изображением
mov byte ptr cs:io_needed, 1; установить флаг
; требующейся записи на диск
cli
call safe_check; проверить, можно ли вызвать DOS,
jc exit_09h_handler
sti
call do_io; если да - записать файл на диск
exit_09h_handler:
pop es
pop ds; восстановить регистры
рора
iret; и вернуться в прерванную программу
int09h_handler endp
hw_reset: retf
; Обработчик INT 08h (IRQ0)
int08h_handler proc far
jmp short actual_int08h_handler; пропустить ISP
old_int08h dd?
dw 424Bh
db 00h
jmp short hw_reset
db 7 dup (0)
actual_int08h_handler:; собственно обработчик
pushf
call dword ptr cs:old_int08h; сначала вызвать стандартный
; обработчик, чтобы он завершил
; аппаратное прерывание (пока оно
; не завершено, запись на диске невозможна)
pusha
push ds
cli; между любой проверкой глобальной переменной
; и принятием решения по ее значению -
; не повторно входимая область, прерывания
; должны быть запрещены
cmp byte ptr cs:io_needed, 0; проверить,
je no_io_needed; нужно ли писать на диск
call safe_check; проверить,
jc no_io_needed; можно ли писать на диск
sti; разрешить прерывания на время записи
call do_io; запись на диск
no_io_needed:
pop ds
рора
iret
int08h_handler endp
; Обработчик INT 13h
; поддерживает флаг занятости INT 13h, который тоже надо проверять перед
; записью на диск
int13h_handler proc far
jmp short actual_int13h_handler; пропустить ISP
old_int13h dd?
dw 424Bh
db 00h
jmp short hw_reset
db 7 dup (0)
actual_int13h_handler:; собственно обработчик
pushf
inc byte ptr cs:bios_busy; увеличить счетчик занятости INT 13h
cli
call dword ptr cs:old_int13h
pushf
dec byte ptr cs:bios_busy; уменьшить счетчик
popf
ret 2; имитация команды IRET, не восстанавливающая
; флаги из стека, так как обработчик INT 13h возвращает некоторые
; результаты в регистре флагов, а не в его копии, хранящейся
; в стеке. Он тоже завершается командой ret 2
int13h_handler endp
; Обработчик INT 28h
; вызывается DOS, когда она ожидает ввода с клавиатуры и функциями DOS можно
; пользоваться
int28h_handler proc far
jmp short actual_int28h_handler; пропустить ISP
old_int28h dd?
dw 424Вh
db 00h
jmp short hw_reset
db 7 dup (0)
actual_int28h_handler:
pushf
push di
push ds
push cs
pop ds
cli
cmp byte ptr io_needed, 0; проверить,
je no_io_needed2; нужно ли писать на диск
lds di, dword ptr in_dos_addr
cmp byte ptr [di+1], 1; проверить,
ja no_io_needed2; можно ли писать на диск (флаг
; занятости DOS не должен быть больше 1)
sti
call do_io; запись на диск
no_io_needed2:
pop ds
pop di
popf
jmp dword ptr cs:old_int28h; переход на старый
; обработчик INT 28h
int28h_handler endp
; Процедура do_grab
; помещает в буфер палитру и содержимое видеопамяти, формируя BMP-файл.
; Считает, что текущий видеорежим - 13h
do_grab proc near
push cs
pop ds
call ems_init; отобразить наш буфер в окно EMS
mov dx, word ptr cs:buffer_seg
mov es, dx; поместить сегмент с буфером в ES и DS
mov ds, dx; для следующих шагов процедуры
mov ax, 1017h; Функция 1017h - чтение палитры VGA
mov bx, 0; начиная с регистра палитры 0,
mov сх, 256; все 256 регистров
mov dx, BMP_header_length; начало палитры в BMP
int 10h; видеосервис BIOS
; перевести палитру из формата, в котором ее показывает функция 1017h
; (три байта на цвет, в каждом байте 6 значимых бит),
; в формат, используемый в BMP-файлах
; (4 байта на цвет, в каждом байте 8 значимых бит)
std; движение от конца к началу
mov si, BMP_header_length+256*3-1; SI - конец 3-байтной палитры
mov di, BMP_header_length+256*4-1; DI - конец 4-байтной палитры
mov сх, 256; СХ - число цветов
adj_pal:
mov al, 0
stosb; записать четвертый байт (0)
lodsb; прочитать третий байт
shl al, 2; масштабировать до 8 бит
push ax
lodsb; прочитать второй байт
shl al, 2; масштабировать до 8 бит
push ax
lodsb; прочитать третий байт
shl al, 2; масштабировать до 8 бит
stosb; и записать эти три байта
pop ax; в обратном порядке
stosb
pop ax
stosb
loop adj_pal
; Копирование видеопамяти в BMP.
; В формате BMP строки изображения записываются от последней к первой, так что
; первый байт соответствует нижнему левому пикселю
cld; движение от начала к концу (по строке)
push 0A000h
pop ds
mov si, 320*200; DS:SI - начало последней строки на экране
mov di, bfoffbits; ES:DI - начало данных в BMP
mov dx, 200; счетчик строк
bmp_write_loop:
mov cx, 320/2; счетчик символов в строке
rep movsw; копировать целыми словами, так быстрее
sub si, 320*2; перевести SI на начало предыдущей строки
dec dx; уменьшить счетчик строк,
jnz bmp_write_loop; если 0 - выйти из цикла
call ems_reset; восстановить состояние EMS
; до вызова do_grab
ret
do_grab endp
; Процедура do_io
; создает файл и записывает в него содержимое буфера
do_io proc near
push cs
pop ds
mov byte ptr io_needed, 0; сбросить флаг требующейся
; записи на диск
call ems_init; отобразить в окно EMS наш буфер
mov ah, 6Ch; Функция DOS 6Ch
mov bx, 2; доступ - на чтение / запись
mov cx, 0; атрибуты - обычный файл
mov dx, 12h; заменять файл, если он существует,
; создавать, если нет
mov si, offset filespec; DS:SI - имя файла
int 21h; создать / открыть файл
mov bx, ax; идентификатор файла - в ВХ
mov ah, 40h; Функция DOS 40h
mov cx, bfsize; размер BMP-файла
mov ds, word ptr buffer_seg
mov dx, 0; DS:DX - буфер для файла
int 21h; запись в файл или устройство
mov ah, 68h; сбросить буфера на диск
int 21h
mov ah, 3Eh; закрыть файл
int 21h
call ems_reset
ret
do_io endp
; Процедура ems_init,
; если буфер расположен в EMS, подготавливает его для чтения / записи
ems_init proc near
cmp dx, word ptr ems_handle; если не используется EMS
cmp dx, 0; (EMS-идентификаторы начинаются с 1),
je ems_init_exit; ничего не делать
mov ax, 4700h; Функция EMS 47h
int 67h; сохранить EMS-контекст
mov ax, 4100h; Функция EMS 41h
int 67h; определить адрес окна EMS
mov word ptr buffer_seg, bx; сохранить его
mov ax, 4400h; Функция EMS 44h
mov bx, 0; начиная со страницы 0,
int 67h; отобразить страницы EMS в окно
mov ax, 4401h
inc bx
int 67h; страница 1
mov ax, 4402h
inc bx
int 67h; страница 2
mov ax, 4403h
inc bx
int 67h; страница 3
ems_init_exit:
ret
ems_init endp
; Процедура ems_reset
; восстанавливает состояние EMS
ems_reset proc near
mov dx, word ptr cs:ems_handle
cmp dx, 0
je ems_reset_exit
mov ax, 4800h; Функция EMS 48h
int 67h; восстановить EMS-контекст
ems_reset_exit:
ret
ems_reset endp
; Процедура safe_check
; возвращает CF = 0, если в данный момент можно пользоваться функциями DOS,
; и CF = 1, если нельзя
safe_check proc near
push es
push cs
pop ds
les di, dword ptr in_dos_addr; адрес флагов занятости DOS,
cmp word ptr es: [di], 0; если один из них не 0,
pop es
jne safe_check_failed; пользоваться DOS нельзя,
cmp byte ptr bios_busy, 0; если выполняется прерывание 13h,
jne safe_check_failed; тоже нельзя
clc; CF = 0
ret
safe_check_failed:
stc; CF = 1
ret
safe_check endp
in_dos_addr dd?; адрес флагов занятости DOS
io_needed db 0; 1, если надо записать файл на диск
bios_busy db 0; 1, если выполняется прерывание INT 13h
buffer_seg dw 0; сегментный адрес буфера для файла
ems_handle dw 0; идентификатор EMS
filespec db 'scrgrb.bmp', 0; имя файла
; Обработчик INT 2Dh
hw_reset2D: retf
int2Dh_handler proc far
jmp short actual_int2Dh_handler; пропустить ISP
old_int2Dh dd?
dw 424Bh
db 00h
jmp short hw_reset2D
db 7 dup (0)
actual_int2Dh_handler:; собственно обработчик
db 80h, 0FCh; начало команды CMP АН, число
mux_id db?; идентификатор программы,
je its_us; если вызывают с чужим АН - это не нас
jmp dword ptr cs:old_int2Dh
its_us:
cmp al, 06; функции AMIS 06h и выше
jae int2D_no; не поддерживаются
cbw; AX = номер функции
mov di, ax; DI = номер функции
shl di, 1; * 2, так как jumptable - таблица слов
jmp word ptr cs:jumptable[di]; переход на обработчик функции
jumptable dw offset int2D_00, offset int2D_no
dw offset int2D_02, offset int2D_no
dw offset int2D_04, offset int2D_05
int2D_00:; проверка наличия
mov al, 0FFh; этот номер занят
mov cx, 0100h; номер версии программы 1.0
push cs
pop dx; DX:DI - адрес AMIS-сигнатуры
mov di, offset amis_sign
iret
int2D_no:; неподдерживаемая функция
mov al, 00h; функция не поддерживается
iret
unload_failed:; сюда передается управление, если хоть один из векторов
; прерываний был перехвачен кем-то после нас
mov al, 01h; выгрузка программы не удалась
iret
int2D_02:; выгрузка программы из памяти
cli; критический участок
push 0
pop ds; DS - сегментный адрес таблицы векторов прерываний
mov ax, cs; наш сегментный адрес
; проверить, все ли перехваченные прерывания по-прежнему указывают на нас,
; обычно достаточно проверить только сегментные адреса (DOS не загрузит другую
; программу с нашим сегментным адресом)
cmp ax, word ptr ds: [09h*4+2]
jne unload_failed
cmp ax, word ptr ds: [13h*4+2]
jne unload_failed
cmp ax, word ptr ds: [08h*4+2]
jne unload_failed
cmp ax, word ptr ds: [28h*4+2]
jne unload_failed
cmp ax, word ptr ds: [2Dh*4+2]
jne unload_failed
push bx; адрес возврата - в стек
push dx
; восстановить старые обработчики прерываний
mov ax, 2509h
lds dx, dword ptr cs:old_int09h
int 21h
mov ax, 2513h
lds dx, dword ptr cs:old_int13h
int 21h
mov ax, 2508h
lds dx, dword ptr cs:old_int08h
int 21h
mov ax, 2528h
lds dx, dword ptr cs:old_int28h
int 21h
mov ax, 252Dh
lds dx, dword ptr cs:old_int2Dh
int 21h
mov dx, word ptr cs:ems_handle; если используется EMS
cmp dx, 0
je no_ems_to_unhook
mov ax, 4500h; функция EMS 45h
int 67h; освободить выделенную память
jmp short ems_unhooked
no_ems_to_unhook:
ems_unhooked:
; собственно выгрузка резидента
mov ah, 51h; Функция DOS 51h
int 21h; получить сегментный адрес PSP
; прерванного процесса (в данном случае
; PSP - копии нашей программы,
; запущенной с ключом /u)
mov word ptr cs: [16h], bx; поместить его в поле
; «сегментный адрес предка» в нашем PSP
pop dx; восстановить адрес возврата из стека
pop bx
mov word ptr cs: [0Ch], dx; и поместить его в поле
mov word ptr cs: [0Ah], bx; «адрес перехода при
; завершении программы» в нашем PSP
pop bx; BX = наш сегментный адрес PSP
mov ah, 50h; Функция DOS 50h
int 21h; установить текущий PSP
; теперь DOS считает наш резидент текущей программой, а scrgrb.com /u -
; вызвавшим его процессом, которому и передаст управление после вызова
; следующей функции
mov ax, 4CFFh; Функция DOS 4Ch
int 21h; завершить программу
int2D_04:; получить список перехваченных прерываний
mov dx, cs; список в DX:BX
mov bx, offset amis_hooklist
iret
int2D_05:; получить список «горячих» клавиш
mov al, 0FFh; функция поддерживается
mov dx, cs; список в DX:BX
mov bx, offset amis_hotkeys
iret
int2Dh_handler endp
; AMIS: сигнатура для резидентной программы
amis_sign db «Cubbi…»; 8 байт
db «ScrnGrab»; 8 байт
db «Simple screen grabber using EMS», 0
; AMIS: список перехваченных прерываний
amis_hooklist db 09h
dw offset int09h_handler
db 08h
dw offset int08h_handler
db 28h
dw offset int28h_handler
db 2Dh
dw offset int2Dh_handler
; AMIS: список «горячих» клавиш
amis_hotkeys db 1
db 1
db 22h; скан-код клавиши (G)
dw 08h; требуемые флаги клавиатуры
dw 0
db 1
; конец резидентной части
; начало процедуры инициализации
initialize proc near
jmp short initialize_entry_point
; пропустить различные варианты выхода без установки резидента,
; помещенные здесь потому, что на них передают управление
; команды условного перехода, имеющие короткий радиус действия
exit_with_message:
mov ah, 9; функция вывода строки на экран
int 21h
ret; выход из программы
already_loaded:; если программа уже загружена в память
cmp byte ptr unloading, 1; если мы не были вызваны с /u
je do_unload
mov dx, offset already_msg
jmp short exit_with_message
no_more_mux:; если свободный идентификатор INT 2Dh не найден
mov dx, offset no_more_mux_msg
jmp short exit_with_message
cant_unload1:; если нельзя выгрузить программу
mov dx, offset cant_unload1_msg
jmp short exit_with_message
do_unload:; выгрузка резидента: при передаче управления сюда АН содержит
; идентификатор программы - 1
inc ah
mov al, 02h; AMIS-функция выгрузки резидента
mov dx, es; адрес возврата
mov bx, offset exit_point; в DX:BX
int 2Dh; вызов нашего резидента через мультиплексор
push cs; если управление пришло сюда -
; выгрузка не произошла
pop ds
mov dx, offset cant_unload2_msg
jmp short exit_with_message
exit_point:; если управление пришло сюда -
push cs; выгрузка произошла
pop ds
mov dx, offset unloaded_msg
push 0; чтобы сработала команда RET для выхода
jmp short exit_with_message
initialize_entry_point:; сюда передается управление в самом начале
cld
cmp byte ptr cmd_line[1], '/'
jne not_unload
cmp byte ptr cmd_line[2], 'u'; если нас вызвали с /u
jne not_unload
mov byte ptr unloading, 1; выгрузить резидент
not_unload:
mov ah, 9
mov dx, offset usage; вывод строки с информацией о программе
int 21h
mov ah, - 1; сканирование от FFh до 01h
more_mux:
mov al, 00h; функция AMIS 00h -
; проверка наличия резидента
int 2Dh; мультиплексорное прерывание
cmp al, 00h; если идентификатор свободен,
jne not_free
mov byte ptr mux_id, ah; вписать его сразу в код обработчика,
jmp short next_mux
not_free:
mov es, dx; иначе - ES:DI = адрес AMIS-сигнатуры
; вызвавшей программы
mov si, offset amis_sign; DS:SI = адрес нашей сигнатуры
mov cx, 16; сравнить первые 16 байт,
repe cmpsb
jcxz already_loaded; если они не совпадают,
next_mux:
dec ah; перейти к следующему идентификатору,
jnz more_mux; если это 0
free_mux_found:
cmp byte ptr unloading, 1; и если нас вызвали для выгрузки,
je cant_unload1; а мы пришли сюда - программы нет в
; памяти,
cmp byte ptr mux_id, 0; если при этом mux_id все еще 0,
je no_more_mux; идентификаторы кончились
; проверка наличия устройства ЕММХХХХ0
mov dx, offset ems_driver
mov ax, 3D00h
int 21h; открыть файл / устройство
jc no_emmx
mov bx, ax
mov ax, 4400h
int 21h; IOCTL: получить состояние файла / устройства
jc no_ems
test dx, 80h; если старший бит DX = 0, ЕММХХХХ0 - файл
jz no_ems
; выделить память под буфер в EMS
mov ax, 4100h; функция EMS 41h
int 67h; получить адрес окна EMS
mov bp, bx; сохранить его пока в ВР
mov ax, 4300h; Функция EMS 43h
mov bx, 4; нам надо 4 * 16 Кб
int 67h; выделить EMS-память (идентификатор в DХ),
cmp ah, 0; если произошла ошибка (нехватка памяти?),
jnz ems_failed; не будем пользоваться EMS,
mov word ptr ems_handle, dx; иначе: сохранить идентификатор
; для резидента
mov ax, 4400h; Функция 44h - отобразить
mov bx, 0; EMS-страницы в окно
int 67h; страница 0
mov ax, 4401h
inc bx
int 67h; страница 1
mov ax, 4402h
inc bx
int 67h; страница 2
mov ax, 4403h
inc bx
int 67h; страница 3
mov dx, offset ems_msg; вывести сообщение об установке в EMS
jmp short ems_used
ems_failed:
no_ems:; если EMS нет или он не работает,
mov ah, 3Eh
int 21h; закрыть файл / устройство ЕММХХХХ0,
no_emmx:
; занять общую память
mov ah, 9
mov dx, offset conv_msg; вывод сообщения об этом
int 21h
mov sp, length_of_program+100h+200h; перенести стек
mov ah, 4Ah; Функция DOS 4Ah
next_segment = length_of_program+100h+200h+0Fh
next_segment = next_segment/16; такая запись нужна только для
; WASM, остальным ассемблерам это
; можно было записать в одну строчку
mov bx, next_segment; уменьшить занятую память, оставив
; текущую длину нашей программы + 100h
; на PSP +200h на стек
int 21h
mov ah, 48h; Функция 48h - выделить память
bfsize_p = bfsize+0Fh
bfsize_p = bfsize_p/16
mov bx, bfsize_p; размер BMP-файла 320x200x256 в 16-байтных
int 21h; параграфах
ems_used:
mov word ptr buffer_seg, ax; сохранить адрес буфера для резидента
; скопировать заголовок BMP-файла в начало буфера
mov cx, BMP_header_length
mov si, offset BMP_header
mov di, 0
mov es, ax
rep movsb
; получить адреса флага занятости DOS и флага критической ошибки (считая, что
; версия DOS старше 3.0)
mov ah, 34 л; Функция 34h - получить флаг занятости
int 21h
dec bx; уменьшить адрес на 1, чтобы он указывал
; на флаг критической ошибки,
mov word ptr in_dos_addr, bx
mov word ptr in_dos_addr+2, es; и сохранить его для резидента
; перехват прерываний
mov ax, 352Dh; АН = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 2Dh
mov word ptr old_int2Dh, bx; и поместить его в old_int2Dh
mov word ptr old_int2Dh+2, es
mov ax, 3528h; AH = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 28h
mov word ptr old_int28h, bx; и поместить его в old_int28h
mov word ptr old_int28h+2, es
mov ax, 3508h; AH = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 08h
mov word ptr old_int08h, bx; и поместить его в old_int08h
mov word ptr old_int08h+2, es
mov ax, 3513h; AH = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 13h
mov word ptr old_int13h, bx; и поместить его в old_int13h
mov word ptr old_int13h+2, es
mov ax, 3509h; AH = 35h, AL = номер прерывания
int 21h; получить адрес обработчика INT 09h
mov word ptr old_int09h, bx; и поместить его в old_int09h
mov word ptr old_int09h+2, es
mov ax, 252Dh; AH = 25h, AL = номер прерывания
mov dx, offset int2Dh_handler; DS:DX - адрес обработчика
int 21h; установить новый обработчик INT 2Dh
mov ax, 2528h; AH = 25h, AL = номер прерывания
mov dx, offset int28h_handler; DS:DX - адрес обработчика
int 21h; установить новый обработчик INT 28h
mov ax, 2508h; AH = 25h, AL = номер прерывания
mov dx, offset int08h_handler; DS:DX - адрес обработчика
int 21h; установить новый обработчик INT 08h
mov ax, 2513h; AH = 25h, AL = номер прерывания
mov dx, offset int13h_handler; DS:DX - адрес обработчика
int 21h; установить новый обработчик INT 13h
mov ax, 2509h; AH = 25h, AL = номер прерывания
mov dx, offset int09h_handler; DS:DX - адрес обработчика
int 21h; установить новый обработчик INT 09h
; освободить память из-под окружения DOS
mov ah, 49h; Функция DOS 49h
mov es, word ptr envseg; ES = сегментный адрес окружения DOS
int 21h; освободить память
; оставить программу резидентной
mov dx, offset initialize; DX - адрес первого байта за концом
; резидентной части
int 27h; завершить выполнение, оставшись
; резидентом
initialize endp
ems_driver db 'EMMXXXX0', 0; имя EMS-драйвера для проверки
; текст, который выдает программа при запуске:
usage db 'Простая программа для копирования экрана только из'
db ' видеорежима 13h', 0Dh, 0Ah
db ' Alt-G - записать копию экрана в scrgrb.bmp'
db 0Dh, 0Ah
db ' scrgrb.com /u - выгрузиться из памяти', 0Dh, 0Ah
db '$'
; тексты, которые выдает программа при успешном выполнении:
ems_msg db 'Загружена в EMS', 0Dh, 0Ah, '$'
conv_msg db 'He загружена в EMS', 0Dh, 0Ah, '$'
unloaded_msg db 'Программа успешно выгружена из памяти', 0Dh, 0Ah, '$'
; тексты, которые выдает программа при ошибках:
already_msg db 'Ошибка: Программа уже загружена', 0Dh, 0Ah, '$'
no_more_mux_msg db 'Ошибка: Слишком много резидентных программ'
db 0Dh, 0Ah, '$'
cant_unload1_msg db 'Ошибка: Программа не обнаружена в памяти', 0Dh, 0Ah, '$'
cant_unload2_msg db 'Ошибка: Другая программа перехватила прерывания'
db 0Dh, 0Ah, '$'
unloading db 0; 1, если нас запустили с ключом /u
; BMP-файл (для изображения 320x200x256)
BMP_header label byte
; файловый заголовок
BMP_file_header db «BM»; сигнатура
dd bfsize; размер файла
dw 0,0; 0
dd bfoffbits; адрес начала BMP_data
; информационный заголовок
BMP_info_header dd bi_size; размер BMP_info_header
dd 320; ширина
dd 200; высота
dw 1; число цветовых плоскостей
dw 8; число бит на пиксель
dd 0; метод сжатия данных
dd 320*200; размер данных
dd 0B13h; разрешение по X (пиксель на метр)
dd 0B13h; разрешение по Y (пиксель на метр)
dd 0; число используемых цветов (0 - все)
dd 0; число важных цветов (0 - все)
bi_size = $-BMP_info_header; размер BMP_info_header
BMP_header_length = $-BMP_header; размер обоих заголовков
bfoffbits = $-BMP_file_header+256*4; размер заголовков + размер палитры
bfsize = $-BMP_file_header+256*4+320*200; размер заголовков +
; размер палитры + размер данных
length_of_program = $-start
end start
В этом примере, достаточно сложном из-за необходимости избегать всех возможностей повторного вызова прерываний DOS и BIOS, добавилась еще одна мера предосторожности - сохранение состояния EMS-памяти перед работой с ней и восстановление в исходное состояние. Действительно, если наш резидент активируется в тот момент, когда какая-то программа работает с EMS, и не выполнит это требование, программа будет читать / писать уже не в свои EMS-страницы, а в наши. Аналогичные предосторожности следует предпринимать всякий раз, когда вызываются функции, затрагивающие какие-нибудь глобальные структуры данных. Например: функции поиска файлов используют буфер DTA, адрес которого надо сохранить (функция DOS 2Fh), затем создать собственный (функция DOS 1Ah) и в конце восстановить DTA прерванного процесса по сохраненному адресу (функция 1Ah). Таким образом надо сохранять / восстанавливать состояние адресной линии А20 (функции XMS 07h и 03h), если резидентная программа хранит часть своих данных или кода в области HMA, сохранять состояние драйвера мыши (INT 33h, функции 17h и 18h), сохранять информацию о последней ошибке DOS (функции DOS 59h и 5D0Ah), и так с каждым ресурсом, который затрагивает резидентная программа. Писать полноценные резидентные программы в DOS сложнее всего, но, если не выходить за рамки реального режима, это - самое эффективное средство управления системой и реализации всего, что только можно реализовать в DOS.
2. Определить значение нескольких векторов, установить новое значение, в процедуре прерывания обработать прерывание от клавиатуры.
; prg15_1.asm
<2> MASM
<3> MODEL small; модель памяти
<4> STACK 256; размер стека
<5> .486p
<6> delay macro time
<7> local ext, iter
<8>; макрос задержки
<9>; На входе - значение переменной задержки (в мкс)
<10> push cx
<11> mov cx, time
<12> ext:
<13> push cx
<14>; в cx одна мкс, это значение можно
<15>; поменять в зависимости от производительности процессора
<16> mov cx, 5000
<17> iter:
<18> loop iter
<19> pop cx
<20> loop ext
<21> pop cx
<22> endm; конец макроса
<23> .data
<24> tonelow dw 2651; нижняя граница звучания 450 Гц
<25> cnt db 0; счетчик для выхода из программы
<26> temp dw?; верхняя граница звучания
<27> old_off8 dw 0; для хранения старых значений вектора
<28> old_seg8 dw 0; сегмент и смещение
<29> time_1ch dw 0; переменная для пересчета
<30> .code; начало сегмента кода
<31> off_1ch equ 1ch*4; смещение вектора 1ch в ТВП
<32> off_0ffh equ 0ffh*4; смещение вектора ffh в ТВП
<33> char db «0»; символ для вывода на экран
<34> maskf db 07h; маска вывода символов на экран
<35> position dw 2000; позиция на экране - почти центр
<36> main proc
<37> mov ax,@data
<38> mov ds, ax
<39> xor ax, ax
<40> cli; запрет аппаратных прерываний на время
<41>; замены векторов прерываний
<42>; замена старого вектора 1ch на адрес new_1ch
<43>; настройка es на начало таблицы векторов
<44>; прерываний - в реальном режиме:
<45> mov ax, 0
<46> mov es, ax
<47>; сохранить старый вектор
<48> mov ax, es: [off_1ch]; смещение старого вектора 1ch в ax
<49> mov old_off8, ax; сохранение смещения в old_off8
<50> mov ax, es: [off_1ch+2]; сегмент старого вектора 1ch в ax
<51> mov old_seg8, ax; сохранение сегмента в old_seg8
<52>; записать новый вектор в таблицу векторов прерываний
<53> mov ax, offset new_1ch; смещение нового обработчика в ax
<54> mov es:off_1ch, ax
<55> push cs
<56> pop ax; настройка ax на cs
<57> mov es:off_1ch+2, ax; запись сегмента
<58>; инициализировать вектор пользовательского прерывания 0ffh
<59> mov ax, offset new_0ffh
<60> mov es:off_0ffh, ax; прерывание 0ffh
<61> push cs
<62> pop ax
<63> mov es:off_0ffh+2, ax
<64> sti; разрешение аппаратных прерываний
<65>; задержка, чтобы новый обработчик таймера вывел символы на экран
<66> delay 3500
<67>; завершение программы
<68> int 0ffh
<69> exit:
<70> mov ax, 4c00h
<71> int 21h
<72> main endp
<73> new_1ch proc; новый обработчик прерывания от таймера
<74>; сохранение в стеке используемых регистров
<75> push ax
<76> push bx
<77> push es
<78> push ds
<79>; настройка ds на cs
<80> push cs
<81> pop ds
<82>; запись в es адреса начала видеопамяти - B800:0000
<83> mov ax, 0b800h
<84> mov es, ax
<85> mov al, char; символ в al
<86> mov ah, maskf; маску вывода - в ah
<87> mov bx, position; позицию на экране - в bx
<88> mov es: [bx], ax; вывод символа в центр экрана
<89> add bx, 2; увеличение позиции
<90> mov position, bx; сохранение новой позиции
<91> inc char; следующий символ
<92>; восстановление используемых регистров:
<93> pop ds
<94> pop es
<95> pop bx
<96> pop ax
<97> iret; возврат из прерывания
<98> new_1ch endp; конец обработчика
<99> new_0ffh proc; новый обработчик пользовательского прерывания
<100> sirena:
<101>; сохранение в стеке используемых регистров
<102> push ax
<103> push bx
<104>; проверка для пересчета на 4:
<105> test time_1ch, 03h
<106> jnz leave_it; если два правых бита не 11, то на выход,; иначе:
<107> go:
<108> mov ax, 0B06h; заносим слово состояния 110110110b
<109>; (0В6h) - выбираем второй канал порта 43h (динамик)
<110> out 43h, ax; в порт 43h
<111> in al, 61h; получим значение порта 61h в al
<112> or al, 3; инициализируем динамик - подаем ток
<113> out 61h, al; в порт 61h
<114> mov cx, 2083; количество шагов
<115> musicup:
<116>; значение нижней границы частоты в ax (1193000/2651=450 Гц),
<117>; где 1193000 - частота динамика
<118> mov ax, tonelow
<119> out 42h, al; в порт 42h - младшее слово ax:al
<120> mov al, ah; обмен между al и ah
<121> out 42h, al; в порте 42h уже старшее слово ax:ah
<122> add tonelow, 1; увеличение частоты
<123> delay 1; задержка на 1 мкс
<124> mov dx, tonelow; текущее значение частоты - в dx
<125> mov temp, dx; в temp - верхнее значение частоты
<126> loop musicup; повторить цикл повышения
<127> mov cx, 2083
<128> musicdown:
<129> mov ax, temp; верхнее значение частоты - в ax
<130> out 42h, al; младший байт ax:al в порт 42h
<131> mov al, ah; обмен между al и ah
<132> out 42h, al; старший байт ax:ah в порт 42h
<133> sub temp, 1; уменьшение частоты
<134> delay 1; задержка на 1 мкс
<135> loop musicdown; повторить цикл понижения
<136> nosound:
<137> in al, 61h; значение порта 61h - в al
<138>; слово состояния 0fch - выключение динамика и таймера
<139> and al, 0fch
<140> out 61h, al; в порт 61h
<141> mov dx, 2651; для последующих циклов
<142> mov tonelow, dx
<143> inc cnt; инкремент количества проходов
<144> cmp cnt, 2; если сирена не звучала двух; раз - повторный запуск
<145> jne go
<146> leave_it:; выход
<147> inc time_1ch; пересчет на 4
<148>; восстановление используемых регистров
<149> pop bx
<150> pop ax
<151>; восстановление вектора прерывания от таймера
<152> cli; запрет аппаратных прерываний
<153> xor ax, ax; снова настройка es на начало таблицы
<154> mov es, ax; векторов прерываний
<155> mov ax, old_off8; запись в таблицу смещения старого
<156> mov es:off_1ch, ax; обработчика прерывания от таймера
<157> mov ax, old_seg8; запись сегмента
<158> mov es:off_1ch+2, ax
<159> sti; разрешение аппаратных прерываний
<160> iret; возврат из прерывания
<161> new_0ffh endp; конец обработчика
<162> end main; конец программы
Список используемой литературы
Бэрри Н. Компьютерные сети. Пер. с англ. - М.: БИНОМ. - 1995. - 400 с.
Джамса К., Лалани С., Уикли С. Программирование в WWW для профессионалов. - Минск. - Попурри. - 1997. - 631 с.
Кент П. World Wide Web: Пер. с англ. - М.: Компьютер. - 1996. - 311 с.
Кулаков Ю.А. Компьютерные сети. - Киев. - 1998. - 384 с.
Компьютерные сети. Принципы, технологии, протоколы/В.Г. Олифер, Н.А. Олифер. - СПб: Питер, 2001. - 672 с.
Максимов Н.В., Партыка Т.Л., Попов И.И. Технические средства информатизации: Учебник. - М.: ФОРУМ: ИНФРА-М, 2005. - 576 с.: ил. - (Профессиональное образование)
Милославская Н.Г., Толстой А.И. Интрасети: доступ в Internet. Защита: Учеб. пособие для вузов. - М.: ЮНИТИ - ДАНА, 200, 527 с.
Колесников Internet: для пользователя. - К.: Издательская группа BHV, 2000.-304 с.
Новомлинский Л. Интернет - торговля. Часть 1/ Сети и системы связи. 1998 - №8.
Новомлинский Л. Интернет - торговля. Часть 2/ Сети и системы связи. 1998 - №9.
Пятибратов А.П. Вычислительные машины, сети и телекоммуникации/ Пятибратов А.П., Гудыно Л.П. - М.: Финансы и статистика. - 1998. - 400 с.
Сеть Internet. Применение в науке и бизнесе/ Горностаев Ю.М. и др. - М.: Россия - 1994. - 136 с.
Сеть Internet./ Горностаев Ю.М. и др. - М.: Россия. - 1993. - 88 с.
Сорокин Л. Аукционы в Интернате - будущее электронной коммерции // Мир электронной коммерции. - 2000. - №1.
Информатика: Учебник. - 3-е перераб. изд. / Под ред. проф. Н.В. Макаровой. - М.: Финансы и статистика, 2000. - 768 с.: ил.
Размещено на Allbest.ru
Подобные документы
Проектирование механизма обработки прерываний. Контроллер прерываний Intel 82C59A. Ввод-вывод по прерыванию. Программируемый контроллер интерфейса Intel 82C55A. Роль процессора в обработке прерывания ввода-вывода. Обзор алгоритма обработки прерывания.
контрольная работа [8,0 M], добавлен 19.05.2010Обработка прерываний - сигналов о совершении некоторых событий в компьютере. Механизм обработки прерываний. Обработка исключений, описание реакции программы на ошибки выполнения. Общее понятие и виды исключительных ситуаций во время выполнения программы.
реферат [192,2 K], добавлен 10.11.2014Изучение понятия, векторов и механизмов обработки прерываний; их классификация в зависимости от источника происхождения. Особенности реагирования аппаратной и программной частей операционной системы на сигналы о совершении некоторого события в компьютере.
реферат [995,8 K], добавлен 22.06.2011Прерывание и его природа. Контролер прерываний. Обработка прерываний в реальном режиме. Характеристики реального режима работы микропроцессора. Схема обработки прерываний в реальном режиме. Написание собственного прерывания. Разработка в общем случае.
доклад [347,0 K], добавлен 22.09.2008Использование недостaтков, присущих различным типам сетей и протоколам без шифровaния дaнных. Куки, аутентификация, шифрование, сниффинг, спуфинг. Метод компромиентации системы. Варианты MITM-атаки. Перехват сессии с использованием утилиты Cookie Cadger.
курсовая работа [1,8 M], добавлен 28.05.2015Принципы и алгоритмы обработки прерываний. Набор действий по реализации этапов обработки прерываний микропроцессора. Разработка структуры и алгоритма резидентной программы. Реализация программы на языке Ассемблер, методы её отладки и тестирования.
курсовая работа [348,7 K], добавлен 22.12.2014Принципы организации и особенности обработки прерываний на основе контроллера 8259A. Общая характеристика аппаратных средств системы прерываний PIC (Programmable Interrupt Controller). История разработки и порядок работы с технологией Plag and Play.
курсовая работа [305,1 K], добавлен 29.07.2010Архитектура микроконтроллеров семейства Mega. Организация памяти. Способы адресации памяти данных. Энергонезависимая память данных. Таблица векторов прерываний. Счетчик команд и выполнение программы. Абсолютный вызов подпрограммы. Сторожевой таймер.
дипломная работа [213,9 K], добавлен 02.04.2009Рассмотрение основных особенностей компьютерной программы Assembler: функции, структурное описание. Характеристика собственных векторов обработчиков прерываний. Div64 как функция-вычислитель, реализующая операцию деления знаковых чисел в формате 64:16.
контрольная работа [224,7 K], добавлен 11.03.2013Разработка и практическая апробация действия драйвер-фильтра USB-накопителя операционной системы Windows, предоставляющего возможности: установка на любой USB накопитель, перехват информации ввода/вывода, запись перехваченной информации в файл на диске.
курсовая работа [349,3 K], добавлен 18.06.2009