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

Резидентный обработчик прерывания 21h (по книге Калашникова)

08.09.2017, 14:12. Показов 2805. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем добрый день.
Изучаю ассемблер по книге Калашникова .
Программа перехватывает 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
CSEG segment
assume cs: CSEG, ds: CSEG, es: CSEG, ss: CSEG
org 100h
    Begin:      
        jmp Init
        Int_21h_proc proc
            cmp ah, 9h
            je Ok_09h
            jmp dword ptr cs:[Int_21h_vect]
            Ok_09h:
                push ds
                push dx
                push cs
                pop ds
                mov dx, offset String_1
                pushf
                call dword ptr cs:[Int_21h_vect]
                pop dx
                pop ds
            iret
            Int_21h_vect dd ?
            String_1 db 'No!!! This is MY string!!!$'
        Int_21h_proc endp
 
        
        Init:
            mov ah, 35h
            mov al, 21h
            int 21h
            mov word ptr Int_21h_vect, bx
            mov word ptr Int_21h_vect + 2, es
            mov ah, 25h
            mov al, 21h
            mov dx, offset Int_21h_proc
            int 21h
            mov dx, offset Init
            int 27h
        CSEG ends
    end Begin

И тут у меня возникло несколько вопросов:
1. Для чего в 9 и 17 строках указывается "cs" ?
Ведь в стороках 30 и 31 мы в "Int_21h_vect" записали (где расположено прерывание int 21h) смещение:сегмент.

Пробовал менять 17 строку на: "call dword ptr [Int_21h_vect]" и "call Int_21h_vect". Работает как и прежде. А с 9-ой строкой так не получается. При вызове 21-го прерывания мы должны попадать на наше "Int_21h_proc", а вызывается оригинальный "int 21h".
2. Почему так происходит?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.09.2017, 14:12
Ответы с готовыми решениями:

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

Обработчик прерывания int 21h (по книге Калашникова)
Доброе время суток, я чтиаю книгу Калашникова-Ассемблер и уже втрой день не могу понять почему обработчик не перехватывает прерывания и не...

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

10
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
08.09.2017, 14:31
Цитата Сообщение от vovvei Посмотреть сообщение
1. Для чего в 9 и 17 строках указывается "cs" ?
Т.к. в DS находится значение из программы пользователя, но к данной переменной нужно обратиться.
1
Asm/C++/Delphi/Py/PHP/VBA
 Аватар для Jin X
6808 / 2048 / 238
Регистрация: 14.12.2014
Сообщений: 4,297
Записей в блоге: 12
08.09.2017, 17:43
По умолчанию при обращении к переменной (точнее, к памяти) применяется сегмент из регистра DS (если только в качестве базового регистра используется не bp/ebp или esp - в этом случае SS). Но т.к. это резидентная программа и, как уже сказали, "в DS находится значение из программы пользователя", то чтобы обратиться к переменной из сегмента нашего резидента (а переменные находятся в том же сегменте, что и код), используем сегмент CS.
3
 Аватар для Ethereal
6773 / 2741 / 385
Регистрация: 17.02.2013
Сообщений: 4,048
11.09.2017, 02:43
Ну и от меня 5 копеек.

Когда управление попадает в обработчик прерывания значение DS не известно. Зато известно значение CS. Оно будет взято из вектора прерывания. А значение вектора прерывания мы и определяли. А каким мы его определяли ?
Цитата Сообщение от vovvei Посмотреть сообщение
mov word ptr Int_21h_vect, bx
mov word ptr Int_21h_vect + 2, es
Собственно тут мы в ту часть вектора прерывания из которой будет взят CS запихали ES. Но при старте COM-программы CS=DS=ES=SS.

Значит что получается ?
Когда управление попадет в обработчик прерывания DS будет неизвестно какое, зато CS будет в точности то каким был DS при старте нашей программы. Вот мы и используем в обработчике прерывания для адресации переменных CS вместо DS.
2
0 / 0 / 0
Регистрация: 24.05.2015
Сообщений: 50
30.10.2017, 15:50  [ТС]
Спасибо всем за ответы.
Дальнейшее изучение приподносит новые вопросы.
Кликните здесь для просмотра всего текста

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.286
CSEG segment
assume cs: CSEG, ds: CSEG, es: CSEG, ss: CSEG
org 100h
     Begin:
        push 0
        pop es
        mov bx, es: [21h*4]
        mov es, es: [21h*4+2]
        mov word ptr cs: [Int_21h_vect], bx
        mov word ptr cs: [Int_21h_vect+2], es
        mov ah, 9
        mov dx, offset String
        pushf
        call dword ptr [Int_21h_vect]
        int 21h
        int 20h
        
        Int_21h_vect dd ?
        String db 'My string!!!', 0Ah, 0Dh, '$'
        CSEG ends
    end Begin


Дойдя до строк
Assembler
1
2
mov bx, es: [21h*4]
mov es, es: [21h*4+2]
Ввожу в DS 0000, чтобы посмотреть что там находится. В BX:ES (смещение:сегмент) должно загрузиться 107C:00A7
problem_1.jpg
А записывается 42B7:0AD2
problem_2.jpg
И переменная Int_21h_vect хранит 42B7:0AD2
Но затем когда заходим в int 21h или call dword ptr [Int_21h_vect], то попадаем туда куда и рассчитывал 107C:00A7
problem_3.jpg
Почему так происходит?

Кликните здесь для просмотра всего текста
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
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
 
Start:
    jmp Init
Int_21h_proc proc
    cmp ah,9        ;Проверим: это функция 09h?
    je Ok_09                ;Если так, то на метку Ok_09 
    jmp dword ptr cs:[Int_21h_vect]
Ok_09:
    push ds         ;Сохраним регистры
    push dx
    push cs         ;Адрес строки должен быть в DS:DX
    pop ds
    mov dx,offset My_string
    pushf           ;Так надо! Позже рассмотрим
    call dword ptr cs:[Int_21h_vect]
    pop dx          ;Восстановим использованные регистры
    pop ds
    iret            ;Продолжим работу (выйдем из прерывания)
Int_21h_vect dd ?
My_string db 'My string!$'
int_21h_proc endp
Init:
    mov ah,35h  ;AH содержит номер функции (это понятно)
    mov al,21h  ;AL указывает номер прерывания, адрес (или вектор)
    int 21h     ;Теперь в ES:BX адрес (вектор) 21h прерывания
    mov word ptr Int_21h_vect,bx
    mov word ptr Int_21h_vect+2,es  ;! Обратите внимание на форму записи
    mov ax,2521h
    mov dx,offset Int_21h_proc  ;DX должен указывать на наш
    int 21h
    mov dx,offset Init
    int 27h
CSEG ends
end Start

А в этом примере почему перед
Assembler
1
jmp dword ptr cs:[Int_21h_vect]
флаги не сохраняем, а перед
Assembler
1
call dword ptr cs:[Int_21h_vect]
сохраняем. Хоть в книге и написано, что перед выходом их call'а стоит iret (флаги, смещение:сегмент), но мы ведь попадаем в одно и то же место. Я думаю, что после джампа назад мы не возвращаемся и флаги поэтому не нужны.
Или аналогично call dword ptr cs:[Int_21h_vect] и int 21h, ведь тоже переходим в одно и тоже место кода, но перед int 21h флаги тоже не сохраняем.
Миниатюры
Резидентный обработчик прерывания 21h (по книге Калашникова)   Резидентный обработчик прерывания 21h (по книге Калашникова)   Резидентный обработчик прерывания 21h (по книге Калашникова)  

0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
30.10.2017, 16:51
Потому, что
1. int 21h эквивалентен двум командам pushf+call [vector 21h].
2. iret эквивалентен двум командам popf+ret.

Когда выполняем jmp на "родной" обработчик, в конце которого стоит iret, то просто сразу отдаём управление в "родной" обработчик и не ждём возврат управления в наш код - управление вернётся той программе, которая вызывала int 21h.

Когда выполняем call, то ожидаем возврат управления в наш обработчик, но в конце родного стоит iret, поэтому перед call сохраняем регистр флагов, т.е. из двух команд "собираем" int.

Т.е. разница между jmp и call в положении нашего обработчика относительно "родного" - кто выполняется первым, а кто вторым.

Почему адреса разные - так вы под отладчиком работаете - сам отладчик очень много перехватывает (почти половину прерываний). Так что вполне возможно несовпадение адресов, которые видны в дампе и которые получаются при выполнении.

Сейчас уже и не вспомню, под DOS была какая-то утилита, показывающая перехваченные прерывания и программы, которые это сделали.
2
30.10.2017, 17:48

Не по теме:

ФедосеевПавел, все разжевал и в рот [ТС]"у положил.. на сей раз хвалю.. вот так бы всегда!!!

0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6206 / 2441 / 402
Регистрация: 29.07.2014
Сообщений: 3,174
Записей в блоге: 4
30.10.2017, 20:03
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
под DOS была какая-то утилита, показывающая перехваченные прерывания
..можно просто дизассемблировать AFD, и посмотреть,
чем он там занимается на старте. AX=25 - установить обработчик:
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
File: AFD.COM
Path: D:\Install\DEBUG\
Size: 65*278
Type: Binary
 
* Entry Point:
.........
 
000001FB: BA0840               mov dx, 4008
000001FE: B80125               mov ax, 2501
00000201: CD21                 int 21
00000203: 8D16FF4A             lea dx, [4AFF]
00000207: B80225               mov ax, 2502
0000020A: CD21                 int 21
0000020C: BA0140               mov dx, 4001
0000020F: B80325               mov ax, 2503
00000212: CD21                 int 21
00000214: 8D166F4B             lea dx, [4B6F]
00000218: B80925               mov ax, 2509
0000021B: CD21                 int 21
0000021D: BAF74A               mov dx, 4AF7
00000220: B81B25               mov ax, 251B
00000223: CD21                 int 21
00000225: 8D166763             lea dx, [6367]
00000229: B82425               mov ax, 2524
0000022C: CD21                 int 21
0000022E: 8D16F13F             lea dx, [3FF1]
00000232: B80025               mov ax, 2500
00000235: CD21                 int 21
00000237: 803E598CFC           cmp byte ptr [8C59], FC
0000023C: 7524                 jne 00000262
0000023E: 8D16C43F             lea dx, [3FC4]
00000242: B80525               mov ax, 2505
00000245: CD21                 int 21
00000247: 8D16F93F             lea dx, [3FF9]
0000024B: B80625               mov ax, 2506
0000024E: CD21                 int 21
00000250: 8D16F93F             lea dx, [3FF9]
00000254: B80725               mov ax, 2507
00000257: CD21                 int 21
00000259: 8D16DD3F             lea dx, [3FDD]
0000025D: B80D25               mov ax, 250D
00000260: CD21                 int 21
0
30.10.2017, 20:56

Не по теме:

Да, дизассемблирование конкретной программы может помочь с информацией об этой программе.

Но есть утилита, кажется, mem (из настоящего DOS, а не из DOSBox), которая показывает текущее состояние перехваченных прерываний и для перехваченных указывает название резидента или драйвера. Эти сведения утилита берёт из MCB (какой-то блок описания выделенной памяти). Возможно, требуется запускать утилиту с неким ключом.
Но это может быть и не mem, а другая утилита.

0
0 / 0 / 0
Регистрация: 24.05.2015
Сообщений: 50
14.11.2017, 15:55  [ТС]
Кликните здесь для просмотра всего текста

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
.286
CSEG segment
assume cs: CSEG, ds: CSEG, es: CSEG, ss: CSEG
org 100h
     Begin:
        push dx
        push ax
        
        mov dx, 050Fh
        xor ax, ax
        xchg dh, al
        mov di, ax
        shl ax, 6
        shl di, 4
        add di, ax
        add di, dx
        shl di, 1
        
        push 0B800h
        pop es
        mov si, offset String
        mov cx, offset Finish - offset String
        mov ah, 0Eh
        Metka:
            lodsb 
            stosw
            dec cx
            cmp cx, 0
        jne Metka
        
        pop ax
        pop dx
        int 20h
        
        String db 'Hello!!!'
        Finish equ $
        CSEG ends
    end Begin

Подскажите пожалуйста почему текст не отображается?
Пробовал сначала на ХР. Через cmd запускаю test.com и ничего не отображается. А если сначала запускаю отладчик(AFD), выхожу из него и запускаю test.com, то строка отображается.
Попробовал на win7, вообще никак не хочет.
0
3410 / 1829 / 489
Регистрация: 28.02.2015
Сообщений: 3,696
14.11.2017, 16:54
Поставьте в начале программы
Assembler
1
2
mov ax,3
int 10h
Книга писалась под COMMAND.COM, который запускался уже в 3-м текстовом режиме.
Начиная с ХР+ CMD.EXE только имитировал работу в этом режиме, при этом видео буфер не создавался, вывод проходил с помощью WAPI прямо в контролер видеокарты. Принудительно запуская 3-й текстовый режим, мы создаем видео буфер и начинаем работу, через него.

AFD сам включает 3-ий режим и не выключает его.
Если наберете в нем М2 В800:0, то правом нижнем окне, через точку будет верхняя строка отладчика
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.11.2017, 16:54
Помогаю со студенческими работами здесь

Резидентный обработчик прерывания клавиатуры: замена символа "a" на "b"
Нужно создать резидентную программу, которая будет заменять определенную букву на другую при вводе с клавиатуры. На данный момент вышло...

Резидентный обработчик прерывания: вывод цветного символа в указанное место экрана
Может кто-нибудь помочь бесплатно найти или решить эту задачу? Заранее спасибо за помощь! Разработать резидентный обработчик прерывания,...

Резидентный обработчик прерывания: вывод на экран сообщение и ожидание подтверждения его получения
Всем привет, ищу помощи в написании такой-вот программы: Разработать резидентный обработчик прерывания, который по истечении...

Резидентный обработчик прерывания, который при нажатии некоторой комбинации клавиш выдает звук
Есть код, вроде правильный. Откомпилировал и создал .exe-файл, после запуска ничего не происходит и DOS зависает. Код написан в ОС DOS на...

Резидентная программа (обработка функции 9h прерывания 21h)
Разбираю программу из калашникова. Должна менять выводимую строку и быть резиднетной. Некуоторое оказалось непонятным что автор написал....


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru