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

Обработчик прерывания int 21h (по книге Калашникова)

13.07.2011, 04:03. Показов 12663. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброе время суток, я чтиаю книгу Калашникова-Ассемблер и уже втрой день не могу понять почему обработчик не перехватывает прерывания и не меняет строку,листинг перехвата 21го прерывания:
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
CSEG segment
 org 100h
  Start:
   ;Переходим на метку инициаллизации. Нам нужно будет перехватить прерывание int 21h, а также оставить программу резидентной в памяти
   
   jmp Init
   
   ; Ниже идет код обработки прерывания 21h (он будет резидентный) .После того ,как процедура выйдет , процедура int_21h_proc останется в памяти и будет контроллировать функцию 09 прерывания 21h.
   
   int_21h_proc proc
   cmp ah,9   ;проверим , это функция 09h ?
   je Ok_09
   
   ; Если нет , перейдем  на оригинальный обработчик 21h. На метку Ok_09 программа уже не вернется
   
   jmp dword ptr cs:[int_21h_vect]
   
   Ok_09:
   push ds; сохраняем регистры
   push dx;
   push cs; Адрес строки должен быть в ds:dx
   pop ds
   
   ;выводим нашу строку (my_string), вмето той, которую должна была вывести программа, вызывающая 21h- прерывание
   
   mov dx,offset my_string
   pushf; эта инструкция здесь необходима
   call dword ptr cs:[int_21h_vect] 
   
   pop dx; Восстановим используемые регистры
   pop ds
   iret; продолжим работу, выйдем из  прерывания
   ;программа ,выводящая строку, считает , что на экране было выведено ее сообщение. Но на самом деле это не так
   
   ;переменная для хранения оригинального обработчика 21h
   int_21h_vect dd ?
   
   my_string db ' Perehvat !$'
   int_21h_proc endp
   
   ;Со следующей метки нашей программы уже не будет в памяти (это нерезидентная часть).
   ; она затрется после выхода(после прерывания 27h)
   
   Init:
   ; установим наш обработчик (int_21h_proc) (адрес нашего обработчика) на прерывние 21h
   ;Но прежде нужно запомнить оригинальный адрес этого прерывания . Для этого используется функция 35h прерывания 21h:
   
   ; ah содержит номер функции
   mov ah,35h ; получаем оригинал
   ;al указывает номер прерывания, адрес (вектор) ,которого нужно получить
   
   mov al,21h
   int 21h
   ;теперь в es:bx адрес (вектор) прерывания 21h (es - сегмент bs-смещение):
   
   mov word ptr int_21h_vect,bx; сохраняем в переменную
   mov word ptr int_21h_vect+2,es
   
   ;адрес сохранили, теперь обрабатываем прерывание:
   mov ax,2521h
   mov dx,offset int_21h_proc ;ds:dx  должны указывать на наш обработчик (т.е int_21h_proc)
   int 21h
   
   ;Теперь если какая-то программа вызовет int 21h, то вначале компъютер попадает на обработчик int_21h_proc.
   ;Осталось завершить программу. оставив ее резидентной в памяти (чтобы никто не затер разработчик, иначе комп висанет)
   
   mov dx,offset Init
   int 27h
   
   ;Прерывание int 27h выходит в ДОС (как 20h) , при этом оставив нашу программу резидентной,
   ;dx должен указывать на последний байт, оставшийся в памяти (это как раз метка Init).То есть в памяти
   ;остается от 000h до адреса по которому метка Init
   
   CSEG ends
   end Start
Файл, на котором тестирую:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CSEG segment
assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
org 100h
 
Begin:
    mov ah,9
    mov dx,offset String
    int 21h
         mov ax,10h
         int 16h
    int 20h
 
String db 'Stroka.$'  ;Пробуем вывести это строку
 
CSEG ends
end Begin
Листинг перехвата 10го прерывания
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
CSEG segment
assume cs:CSEG, ds:CSEG, ss:CSEG, es:CSEG
org 100h
 
Begin:
       jmp Init ;На метку инициализации 
 
 
; === Процедура обработки 10h прерывания ===
Int_10h_proc proc
      pushf ;Сохраним флаги в стеке, т.к. они поменяются...
 
      cmp ax,8899h  ;Проверим на повторную загрузку в память (см. ниже)
      jne Next_test ;Если не проверка, то смотрим дальше... 
 
      xchg ah,al    ;Меняем местами AH и AL (признак того, что мы в памяти
            ;что-то вроде ответного сигнала)
      popf  ;Выровним стек
      iret  ;Выйдем из прерывания (вернемся в нашу программу)
            ;AX теперь равен 9988h !!!
 
Next_test:
      cmp ah,88h    ;Это вызов нашей функции?
      jne Go_10h    ;Если нет - уйдем в оригинальный обработчик 10h 
 
      push es       ;Сохраним ES...
 
      mov ax,0B800h ;...и занесем в него сегмент 0-ой страницы дисплея
      mov es,ax
 
      xor di,di     ;Подготвимся к чистке экрана (равносильно mov di,0)
      mov cx,2000   ;Просто "забьем" его пробелами.
      mov ax,0720h  ;Будем заносить: код цвета (07) / символ пробела (20h)
      rep stosw     ;"Забиваем"... Очень быстро...
 
      mov di,1014   ;Будем выводить вот отсюда (примерно центр экрана)
      mov ah,14     ;С такими атрибутами (светло-желтый)
 
Next_sym:
      lodsb     ;Заносим в AL очередной символ (один байт, т.к. lodsB),
            ;Расположенный по адресу DS:SI, увеличив затем SI
            ;на единицу
 
      cmp al,0      ;Конец строки?
      jz Stop_out   ;Да - на выход... 
 
      stosw ;Заносим по адресу ES:DI значение из AX и увеличиваем DI на 2
        ;Здесь заносим слово, т.к. stosW, поэтому на два и
        ;увеличивается значение DI
 
      jmp short Next_sym ;Следующий символ... 
             ;SHORT (короткий) - делает в некоторых случаях
             ;команду jmp на один байт короче.
             ;Работает ТОЛЬКО в том случае, если между меткой
             ;и jmp расстояние не более 127 байт!
 
Stop_out:
      pop es    ;Если достигли конца строки, то восстановим регистры,
      popf  ;выровнив стек...
      iret  ;...и выйдем из прерывания
 
Go_10h:
      popf  ;Выровним стек
      jmp dword ptr cs:[Int_10h_vect]   ;"Прыгаем" на оригинальный обработчик
 
Int_10h_vect dd ? ;Здесь хранится адрес оргинального обработчика
Int_10h_proc endp
 
 
; ===============================================================
; Инициализация (подготовка и настройка резидента)
Init:
       mov ax,8899h ;Проверим, в памяти ли мы уже или еще нет
       int 10h      ;8899h - наш позывной
       cmp ax,9988h ;Отозвался обработчик (AH/AL должены поменяться местами)?
       jne Set_resident
 
       mov ah,9     ;Если в памяти, то выведем соответствующее сообщение
       mov dx,offset In_memory ;Зачем нас двое в памяти?
       int 21h
 
       ret      ;...И вернемся в DOS
 
 
Set_resident:       ;Если нас в памяти нет, то установим резидент
       mov ax,3510h
     int 21h        
[B]; Зачем здесь 21 прерывание ,если идет перехвыт 10го , или ф-я 35h неотъемлема от прерывния 21h для перехвата?[/B]
 
;Получим и сохраним адрес (вектор) 10h прерывания
       mov word ptr Int_10h_vect,bx ;Вначале младшее слово (смещение)
       mov word ptr Int_10h_vect+2,es   ;Затем старшее (сегмент)
 
       mov ax,2510h
       mov dx,offset Int_10h_proc
       int 21h      ;"Повесим" нашу процедуру на 10h прерывание
 
       mov dx,offset Init
       int 27h      ;Оставим программу резидентной в памяти.
 
In_memory db 'Мы уже в памяти!!!!$'
 
CSEG ends
end Begin
Да, и если считаете,что данная книга тяжелая для первого ознакомления, посоветуйте пожалуйста какую-то другую, желательно, в которой речь шла бы о системном программировании и о создании антивирусов и вирусов на языке ассемблер.
Спасибо за внимание,если что не так написал, извините,на данном форуме впервые и с ассемблером стаклкиваюсь впервые, а вещь очень нужная

Добавлено через 43 минуты
Да, и зачем в листинге call dword ptr cs:[int_21h_vect] , jmp dword ptr cs:[int_21h_vect],что оно означает, ведь такой процедуры нет, или это ссылка на переменную, в которой хранится адрес 21го прерывания.К сожалению , в учебнике не объясняются все вещи сразу.

Добавлено через 2 минуты
Да, и зачем в листинге 1 call dword ptr cs:[int_21h_vect] , jmp dword ptr cs:[int_21h_vect],что оно означает, ведь такой процедуры нет, или это ссылка на переменную, в которой хранится адрес 21го прерывания.К сожалению , в учебнике не объясняются все вещи сразу.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.07.2011, 04:03
Ответы с готовыми решениями:

Резидентный обработчик прерывания 21h (по книге Калашникова)
Всем добрый день. Изучаю ассемблер по книге Калашникова . Программа перехватывает 21-ое прерывание и подменивает выводимую строку. ...

Резидентный обработчик 21h прерывания (из 10-й главы Калашникова)
Имеется вот такой код резидентного обработчика прерываний, написанный предположительно на MASM данная программа должна после выполнения...

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

17
 Аватар для zzzyyyxxx
768 / 312 / 11
Регистрация: 27.05.2011
Сообщений: 703
13.07.2011, 06:58
пример перехвата 21го прерывания рабочий и файл для тестирования тоже,
единственный момент,

в перехвате допиши это - [2. assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG]

и bat файл такой:
c:\tasm\bin\tasm prog.asm
c:\tasm\bin\tlink /t prog.obj
pause
0
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
13.07.2011, 19:27  [ТС]
Странно, но у меня почему-то выводится исходная строка из теста, а не строка из перехвата
0
 Аватар для zzzyyyxxx
768 / 312 / 11
Регистрация: 27.05.2011
Сообщений: 703
13.07.2011, 21:49
Зайди в пуск->выполнить->cmd.
После запуска, пропиши путь к перехватчику.
Далее укажи путь, к тест-файлу и ВСЁ.

P.S.: Для того, чтобы не возиться с путями, скинь оба файла в корень диска
0
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
14.07.2011, 00:45  [ТС]
Да,прописывал
C:\Assembler\MASM611\BIN\ML.EXE PROG10.ASM /AT
C:\Assembler\MASM611\BIN\ML.EXE Test10.ASM /AT
Сгенерировались com-файлы и ни фига, не перехватывает
0
 Аватар для zzzyyyxxx
768 / 312 / 11
Регистрация: 27.05.2011
Сообщений: 703
14.07.2011, 07:55
ну так бы сразу написал бы, что используешь MASM.
с MASM в DOS я не работал, так что чё к чему не знаю, использую его тока для WIN,
если это не принципиально, то вот TASM:
Вложения
Тип файла: rar TASM.rar (162.9 Кб, 102 просмотров)
2
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
14.07.2011, 13:42
Tetr1s, вы как тестируете ?
0
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
15.07.2011, 03:44  [ТС]
Спасибо, через TASM все работает
0
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
16.07.2011, 05:06  [ТС]
Прошу прощение, я немного ошибся в названиях файлов при тестировании через TASM, через TASM тоже не перехватывает,тестирую так:
Пуск->Выполнить->
c:\Assembler\TASM\tasm prog10.asm
c:\Assembler\TASM\tlink /t prog10.obj
запускаю сгенерированный .com файл
потом гененрирую
c:\Assembler\TASM\tasm test10.asm
c:\Assembler\TASM\tlink /t test10.obj
запускаю сгенерированный .com файл
и выводится исходная строка
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
16.07.2011, 13:26
Ну а как вы "запускаете сгенерированный .com файл" ?
0
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
18.07.2011, 01:14  [ТС]
Двойным кликом по .com файлу
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
18.07.2011, 05:02
А почему все это не в cmd, как вам посоветовали выше ?
1
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
19.07.2011, 02:13  [ТС]
Спасибо,заработало, а не подскажите, почему через клики не работало?
и какой учебник по ассемблеру сгодится для первого ознакомления, может мне еще рано читать Калашникова??Может начать с классического для ВУЗов,такого, как Юров?Так как с ассеммблером с первого курса не сталкивался,и тогда не особо понимал зачем он нужен,потребность а нем возникла после изучения языков высокого уровня.
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
19.07.2011, 04:50
Цитата Сообщение от Tetr1s Посмотреть сообщение
почему через клики не работало?
Потому что при запуске каждый раз создавалась новая виртуальная машина с досом, а после запуска cmd все происходило внутри одной машины.
0
1 / 1 / 0
Регистрация: 08.07.2011
Сообщений: 50
19.07.2011, 04:54  [ТС]
спасибо
0
procamist
05.11.2012, 11:11
Вопрос по первому обработчику прерываний
Assembler
1
2
3
4
5
6
7
 ...
   push ds; сохраняем регистры
   push dx;
   push cs; Адрес строки должен быть в ds:dx
   pop ds
   mov dx,offset my_string
...
Вот тут почему мы в ds заносим cs? мне казалось что cs указывает на сегмент кода программы которая вызвала прерывание. Следовательно получается теперь НАША строка будет находится в сегменте кода вызывающей программы со смещением как в обработчике?
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
05.11.2012, 12:05
Тут весь код в одном сегменте.
0
procamist
05.11.2012, 13:48
При запуске программы-теста , обработчик находится в одном сегменте, а программа в другом? если так то получается что в

обработчике адрес ds:dx будет указывать на сегмент кода программы, а смещение на строку в обработчике... вроде так..


и еще вопрос про
jmp dword ptr cs:[int_21h_vect]

в коде вот таком

...
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CSEG segment
org 100h
Begin:
        
mov ax,3         
int 10h     
 
mov ax,0B800h
mov es,ax   
mov di,0
mov al,1
mov ah,31
mov es:[di],ax
        
mov ah,10h  
int 16h
    
int 20h
 
CSEG ends
end Begin
...

Здесь mov es:[di],ax мы заносим значение ax по адресу, а di - это вроде смещение, но тут
jmp dword ptr cs:[int_21h_vect]

[int_21h_vect] - 4 байтная переменная содержащая и смещение и сегмент, то есть мы прыгаем по смещение:[смещение сегмент]
это как?
и зачем тут dword ptr?
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.11.2012, 13:48
Помогаю со студенческими работами здесь

Резидентная программа - перехват прерывания int 21h ah=09h
Задание: перекрыть 9 функцию 21 прерывания в assembler. Помогите, плиз, разобраться как правильно ставить перекрывание. Решил с самого...

Почему при вызове функции 4ch прерывания 21h резидентный обработчик падает?
Написал резидентную программу, всё работает, но если моя или другие программы вызывают функцию 4ch прерывания 21h, консоль перестаёт...

Резидент: Вывод таблицы векторов прерывания не используя int 21H
Нужно вывести на экран Ms DOs таблицу векторов прерывания НЕ используя int 21H! так что я предполагаю через int 10H.. уже неделю с этим...

Перехват прерывания int 21h ah=0Ah: во вводимой строке продублировать все гласные буквы
Привет всем, задали тут задачку: -Переопределить десятую функцию прерывания 21h таким образом, чтобы в вводимой строке были...

Вывод на экран сообщения функцией 9Н прерывания INT 21H
Определите данные и напишите команды, необходимые для вывода на экран функцией 9Н прерывания INT 21H сообщения “What is the current date...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru