Форум программистов, компьютерный форум, киберфорум
Assembler: DOS/Real Mode/16-bits
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.61/41: Рейтинг темы: голосов - 41, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 15.04.2012
Сообщений: 20
1

[Вопрос] Перехват прерывания прямым доступом к вектору прерывания

06.05.2012, 21:01. Показов 8404. Ответов 20
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всех приветствую!
В данный момент разбираюсь с обработкой аппаратного прерывания (прерывание таймера 08h и 1Ch, -//- клавиатуры 09h). Освоил способ с помощью функций 25h и 35h.
Но не могу понять, как сделать тоже самое прямой записью (установить и возвратить текущее значение вектора..).
Прошу помощи!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.05.2012, 21:01
Ответы с готовыми решениями:

Перехват прерывания 20h
Здравствуйте. Пытаюсь перехватить прерывание 20h, вывести строку, а потом восстановить адрес...

Вычислить адрес вектора прерывания по номеру прерывания.
17. По заданному номеру прерывания (13 h) вычислите логические адреса хранения исходных адресов...

Перехват прерывания int 09h
напишите пожалуйста почему перехват прерывания происходит именно в этой строчке int 16h ...

Перехват прерывания, скроллинг экрана
Необходимо реализовать программу на ассемблере (emu8086). Заполнить экран произвольной...

20
116 / 136 / 0
Регистрация: 15.04.2012
Сообщений: 1,031
07.05.2012, 07:07 2
Это задачка очень простая. Вектора прерывания находится в памяти по адресу 0000h:0000h. Вначале идет смещение, затем сегмент. Например, тебе нужно обработчик на 8 прерывание посадить. 8*4(длина элемента) = 20h, то есть по адресу 0000H:0020h находится смещение обработчика прерывания, а по адресу 0000H:0022h - сегмент обработчика. Просто читаешь оттуда начальный адрес, сохраняешь его у себя в резидентной, затем запихиваешь туда адрес своего обработчика и остаешься резидентом. Когда выходишь читаешь из своего буфера, ставишь по адресу исходный адрес и выходишь.
0
650 / 337 / 37
Регистрация: 04.04.2012
Сообщений: 886
07.05.2012, 10:47 3
Немного добавлю. Перед изменением в системной области память, надо запретить аппаратные прерывания командой CLI, а после внесения изменений разрешить - STI. Так надежней будет.
0
116 / 136 / 0
Регистрация: 15.04.2012
Сообщений: 1,031
07.05.2012, 13:54 4
А, ну да, я у Калашникова читал такое про изменение стековых указателей. Это правда, особенно про таймер, потому что таймер может вылететь чертикуда. И непонятно, что будет с ДОСОм. Скорее всего упадет.
0
0 / 0 / 0
Регистрация: 15.04.2012
Сообщений: 20
07.05.2012, 19:03  [ТС] 5

Не по теме:

не получилось на готовом примере(


Вот код, работает с функциями 35h\25h, но стоит "попытаться" напрямую к вектору обратится, то зацикливается... Может не так обращаюсь. Вот код оригинальной программы (могу и свою с ошибками):
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
;INT_N  equ 8   ;прерывание таймера (IRQ0)
;INT_N  equ 9   ;прерывание клавиатуры (IRQ1)
INT_N   equ 1Ch ;прерывание таймера BIOS - программный аналог int 8
 
.186
.model small
.stack 2048
 
.code
 
;----- данные ----
;(расположены в секции кода для удобного доступа из обработчика)
 
;адрес предыдущего обработчика прерывания
old_int     label dword
old_int_o   dw ?
old_int_s   dw ?
 
;символ и аттрибут для вывода на экран
char0       label word
            db '*'
attr0       db 0
 
;----- обработчик прерывания -----
int_proc:
    pusha
    push es
    mov ax,0B800h
    mov es,ax
    xor di,di
    cld
    mov ax,char0
    mov cx,80
set_attr:
    and ah,0Fh
    stosw
    inc ah
    loop set_attr
    inc ah
    mov attr0,ah
    pop es
    popa
    jmp old_int 
 
;----- основная программа -----
entry:
;установка текстового видеорежима 80x25, 16 цветов
    mov ax,3
    int 10h
 
;получение адреса текущего обработчика прерывания   
    mov ax,3500h or INT_N
    int 21h
    mov old_int_o,bx
    mov old_int_s,es
;установка нового обработчика
    mov ax,2500h or INT_N
    lea dx,int_proc
    push cs
    pop ds
    int 21h
 
;ждать нажатия клавиши Escape
wait_esc:
    mov ah,8
    int 21h
    cmp al,27
    jne wait_esc
 
;восстановить стандартную обработку прерывания
    mov ax,2500h or INT_N
    lds dx,old_int
    int 21h
 
;выход из программы 
    mov ax,4C00h
    int 21h
 
end entry
0
116 / 136 / 0
Регистрация: 15.04.2012
Сообщений: 1,031
08.05.2012, 07:33 6
Цитата Сообщение от Go.D-bq Посмотреть сообщение
mov ax,2500h or INT_N
О, какой подход прикольный.
Go.D-bq, знаешь почему у тебя виснет. Ты ставь вначале cli и sti после, потому что если кто-то обратится к прерыванию, когда ты меняешь, то пойдет программа непонятно куда. Мой совет - cli перед сменой и sti после смены. Ну а для таймера это просто обязательно. Int 25h и Int 35h блокирует прерывания перед сменой тоже.
1
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
08.05.2012, 10:34 7
ВотЪ, поправил немножко.О_о
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
;INT_N  equ 8   ;прерывание таймера (IRQ0)
;INT_N  equ 9   ;прерывание клавиатуры (IRQ1)
INT_N   equ 1Ch         ;прерывание таймера BIOS - программный аналог int 8
Vector_1Ch_ofs  Equ 4*1Ch   ;
Vector_1Ch_seg  Equ 4*1Ch+2 ;
 
.model  small
.386
.stack  2048
 
.code
 
;----- данные ----
;(расположены в секции кода для удобного доступа из обработчика)
 
;адрес предыдущего обработчика прерывани
;old_int     label dword
;old_int_o   dw ?
;old_int_s   dw ?
    Old_isr1C   dd ?
;символ и аттрибут для вывода на экран
    char0   label word
    db  '*'
    attr0   db 0
 
;----- обработчик прерывания -----
int_proc:
    pushf
    call    dword ptr cs:Old_isr1C
    pusha
    push    es
    mov ax,0B800h
    mov es,ax
    xor di,di
    cld
    mov ax,char0
    mov cx,80
set_attr:
    and ah,0Fh
    stosw
    inc ah
    loop    set_attr
    inc ah
    mov attr0,ah
    pop es
    popa
    retf    2
 
;----- основная программа -----
entry:
;установка текстового видеорежима 80x25, 16 цветов
    mov ax,3
    int 10h
 
;получение адреса текущего обработчика прерывани
    push    es
    push    0
    pop es
    push    word ptr es:Vector_1Ch_seg;
    push    word ptr es:Vector_1Ch_ofs
    pop word ptr cs:Old_isr1C   ;
    pop word ptr cs:Old_isr1C+2
;установка нового обработчика
    cli
    push    offset int_proc
    push    cs
    pop word ptr es:Vector_1Ch_seg
    pop word ptr es:Vector_1Ch_ofs
    sti
    pop es
;ждать нажатия клавиши Escape
wait_esc:
    mov ah,8
    int 21h
    cmp al,27
    jne wait_esc
 
;восстановить стандартную обработку прерывани
    mov ax,2500h or INT_N
    lds dx, Old_isr1C
    int 21h
 
;выход из программы
    mov ax,4C00h
    int 21h
 
    end entry
Цитата Сообщение от programmisto
mov ax,2500h or INT_N
О, какой подход прикольный.
Слепи макрос. Слабо?
1
116 / 136 / 0
Регистрация: 15.04.2012
Сообщений: 1,031
08.05.2012, 13:53 8
Цитата Сообщение от Charles Kludge Посмотреть сообщение
Слепи макрос. Слабо?
Нет. Вот макрос для замены вектора в DS:SI адрес нового обработчика, в CL - номер:
Assembler
1
2
3
4
5
6
setvector macro
mov dx,si
mov al,cl
mov ah,35h
int 21h
setvector endm
и для получения, в CL - номер прерывания, на выходе: DX:SI - адрес вектора
Assembler
1
2
3
4
5
6
getvector macro
mov al,cl
mov ah,25h
int 21h
mov si,dx
getvector endm
ВСЕ!
0
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
08.05.2012, 14:29 9
Цитата Сообщение от programmisto
ВСЕ!
Копипаста не в счёт. К тому же там mov al, cl - лишнее.
Через замену обработчика напрямую, сохранение старого и т.д. Типа SetVector IntNum, MyHandler и RestoreVector IntNum. Ы?
0
0 / 0 / 0
Регистрация: 15.04.2012
Сообщений: 20
08.05.2012, 16:02  [ТС] 10
Ребят, благодарю!

Не по теме:

сижу вот теперь в отладчик, с листом бумаги и разбираюсь: втолкнул в стек, вытолкнул из стека..:umnik:


Код получается снова нагруженный.. Просто я не знаю шаблона для простого написания прерывания.. Части раскиданы по все программе
Есть какая-нибудь программа, на которую можно опереться как шаблон? Что-то типа этого не встречали? : процедура (вызов-запрет-цикл выводимого сообщений) - главная часть - EXIT ?

Не по теме:

Может просто где натыкались на такое.. А то будет сложно потом знакомым объяснять другим что за функции типа retf или lds своими словами.

0
116 / 136 / 0
Регистрация: 15.04.2012
Сообщений: 1,031
09.05.2012, 06:25 11
Цитата Сообщение от Go.D-bq Посмотреть сообщение
опереться как шаблон
Смотри образец обработчика прерывания:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
olddat dd 0
 
push 0
pop es
mov bx,номер прерывания*4
mov olddat,es:[bx]
mov es:[bx],word ptr offset Int_x_proc
mov es:[bx+2],word ptr seg Int_x_proc
 
Int_x_proc proc
 
;здесь делаем махинации.
 
push [olddat+2]
pop es
mov bx,[olddat]
call es:bx
iret
Int_x_proc endp
int 21h
;оставляем резидентной
P.S.эксперты, подскажите, как прогу резидентной оставить. Справочку небольшую.
1
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
09.05.2012, 08:40 12
Цитата Сообщение от programmisto
Справочку небольшую.
RU.ASM.CHAINIK FAQ :rtfm:
0
0 / 0 / 0
Регистрация: 15.04.2012
Сообщений: 20
12.05.2012, 13:08  [ТС] 13

Не по теме:

Виноват за долгую задержку в коде ;)


Проверьте на правильность, может что лучше заменить-переделать?
Вопрос в шапке указан! Вот сам код! :
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
.model  small
.386
.stack  200h
.code
 
;----- данные ----
;(расположены в секции кода для удобного доступа из обработчика)
 
;адрес предыдущего обработчика прерывани
    Old_1Ch   dd ?
;символ и аттрибут для вывода на экран
    char   label word
    db  '*'     ;00101010b
    attr   db 0
;----- обработчик прерывания -----
int_proc_1Ch:
    pushf
    call    dword ptr cs:Old_1Ch
    pusha
    push    es
    mov ax,0B800h
    mov es,ax
    xor di,di
    cld
    mov ax,char
    mov cx,80
set_attr:
    and ah,00001111b
    mov es:[di],ax
    add di,2
    inc ah
    loop    set_attr
    inc ah
    mov attr,ah
    pop es
    popa
    iret
;----- основная программа -----
main:
;установка текстового видеорежима 80x25, 16 цветов, + очистка экрана 
    mov ax,3
    int 10h
;получение адреса текущего обработчика прерывани
    push    es
    push    0
    pop es
    push    word ptr es:4*1Ch+2;
    push    word ptr es:4*1Ch 
    pop word ptr cs:Old_1Ch   ;
    pop word ptr cs:Old_1Ch+2
;установка нового обработчика
    cli
    push    offset int_proc_1Ch
    push    cs
    pop word ptr es:4*1Ch+2
    pop word ptr es:4*1Ch 
    sti
    pop es
;ждать нажатия клавиши Esc
wait_esc:
    mov ah,8
    int 21h
    cmp al,27
    jne wait_esc
;восстановить стандартную обработку прерывани
    mov dx,word ptr Old_1Ch
    mov ds,word ptr Old_1Ch+2
;выход из программы
    mov ax,4C00h
    int 21h
    end main
0
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
12.05.2012, 13:16 14
стр. 29,30 можно заменить на одну:
Assembler
1
stosw
0
Go.D-bq
12.05.2012, 14:02  [ТС]
  #15

Не по теме:

Момент всплыл грустный: программа то отработает нормально, то может с ошибкой.. Перепроверил код - тщетно.
Не знаю куда копать пока...

0
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
12.05.2012, 14:09 16
В стр. 68 забыто восстановление старого вектора.
0
0 / 0 / 0
Регистрация: 15.04.2012
Сообщений: 20
12.05.2012, 14:44  [ТС] 17
Понятно. Просто суть была перевести команды:
Assembler
1
2
3
mov ax,2500h or 1Ch
    lds dx, Old_1C
    int 21h
в эквивалентные с прямой записью :) Но я не справился(

Не по теме:

Исправляю ..

0
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
12.05.2012, 14:57 18
Цитата Сообщение от Go.D-bq
Но я не справился(
Кхе... Лишнее зачеркнуть:
Assembler
1
2
3
4
5
6
7
8
9
;восстановить стандартную обработку прерывани
    push    es
    push    0
    pop es
    cli 
    push    dword ptr cs:Old_isr1C
    pop dword ptr es:4*1Ch
    sti
    pop es
0
0 / 0 / 0
Регистрация: 15.04.2012
Сообщений: 20
12.05.2012, 15:05  [ТС] 19
Charles Kludge Сделал так:
Assembler
1
2
3
4
5
6
7
push 0
    pop es
    pushf
    cli 
    mov eax,dword ptr Old_1Ch
    mov dword ptr es:[4*1Ch],eax
    popf

Не по теме:

Сделал сам и вижу ваш код :) Все равно благодарю! :good:

0
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
12.05.2012, 15:14 20
Может, pushf/popf убрать, а вместо popf - sti ? И pop es забыт.
0
12.05.2012, 15:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.05.2012, 15:14
Помогаю со студенческими работами здесь

Перехват прерывания int 21h
Немного решил поэкспериментировать. Есть два случая для сравнения. Первый случай (работает):...

Глобальный перехват аппаратного прерывания
Такой вопрос: обычный перехват прерывания клавиатуры (написанный под ДОС) работает только в рамках...

Перехват прерывания жесткого диска
здр. вот, например, существует int 13h - сервис BIOS для работы с диском на низком уровне (чтение,...

Вывод на экран. Перехват прерывания int 05h
Очистить экран. Вывести несколько строк произвольного текста. Пе- рехватить прерывание экрана (Int...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru