20.11.2017, 14:50 [+3 UTC]
в нашей команде: 2 271 чел. | участники онлайн: 9 (рекорд: 21)

:: РЕГИСТРАЦИЯ

:: консультации

:: задать вопрос

:: все разделы

:: правила

:: новости

:: участники

:: доска почёта

:: форум

:: блоги

:: поиск

:: статистика

:: наш журнал

:: наши встречи

:: наша галерея

:: отзывы о нас

:: поддержка

:: руководство

Версия системы:
7.41 (25.02.2017)

Общие новости:
23.02.2017, 09:51

Форум:
20.11.2017, 14:46

Последний вопрос:
20.11.2017, 14:10

Последний ответ:
20.11.2017, 11:49

Последняя рассылка:
20.11.2017, 06:15

Писем в очереди:
0

Мы в соцсетях:

Наша кнопка:

RFpro.ru - здесь вам помогут!

Отзывы о нас:
31.05.2010, 22:37 »
Болдырев Тимофей
Спасибо большое! [вопрос № 178740, ответ № 261773]
01.08.2012, 19:33 »
korsar
Благодарю за хороший ответ. А насчёт 30 и более тысяч всё-таки с вами не соглашусь, уж больно просто и узок круг задач, требуемый от ноутбука для такой большой суммы. Для всего остального у меня есть комп smile [вопрос № 186479, ответ № 271372]

РАЗДЕЛ • Assembler

Создание программ на языке Assembler.

[администратор рассылки: Лысков Игорь Витальевич (Старший модератор)]

Лучшие эксперты в этом разделе

Коцюрбенко Алексей aka Жерар
Статус: Мастер-Эксперт
Рейтинг: 313
Зенченко Константин Николаевич
Статус: Модератор
Рейтинг: 285
Лысков Игорь Витальевич
Статус: Старший модератор
Рейтинг: 168

Перейти к консультации №:
 

Консультация онлайн # 191241
Раздел: • Assembler
Автор вопроса: Caesar (Посетитель)
Отправлена: 24.07.2017, 13:03
Поступило ответов: 1

Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Как правильно прочитать и понять команды:
1.

Код (Assembler) :: выделить код
jmp dword ptr cs:[Int_21h_vect]

2.
Код (Assembler) :: выделить код
Int_21h_vect dd ?

3.
Код (Assembler) :: выделить код
mov word ptr Int_21h_vect, bx
mov word ptr Int_21h_vect+2, es

Состояние: Консультация закрыта

Ответ # 275165 от Лысков Игорь Витальевич (Старший модератор)

Здравствуйте, Caesar!
1)Вектора, т.е. подпрограммы отработки прерывания в ДОСе представляют собой
длинные указатели, состоящие из смещения и сегмента. Все они записаны в начале памяти,
начиная с 0 адреса, на каждый адрес отводится по 4 байта.
2)В системе может быть несколько программ, которые "висят" на каком-то векторе.
Это может быть, как сама система, так и резиденты, плюс текущая программа.
Поэтому необходимо при установке собственного обработчика прерывания
позаботиться о сохранении адреса предыдущего обработчика вектора.
и отдаче туда управления, после того, как отработали свою функцию или вообще увидели, что
пришедшую функцию нам отрабатывать не надо.
Т.о., мы встраиваемся в цепочку обработчиков текущего вектора.
После выхода из программы (если, конечно, программа - не резидент) необходимо позаботиться о
восстановлении вектора прерывания на предыдущий обработчик.
3) Как это делается?
Пред установкой своего обработчика прерывания читаем адрес текущего при помощи

Код (Assembler) :: выделить код
mov ah=35h ;функция
mov al=21h ;интересующий номер прерывания
int 21h
получаем в bx смещение и в es - сегмент старого обработчика прерывания
И сохраняем в двойном слове
Код (Assembler) :: выделить код
Int_21h_vect dd ?
при помощи команд
Код (Assembler) :: выделить код
mov word ptr Int_21h_vect, bx
mov word ptr Int_21h_vect+2, es
Далее, в том месте, где надо отдать управление старому обработчику делаем длинный переход
Код (Assembler) :: выделить код
jmp dword ptr cs:[Int_21h_vect]
который поменяет и смещение и сегмент, т.о. управление передастся предыдущему обработчику

Как читать? Да так и читать:
1) длинный переход по длинному адресу, хранящемуся в Int_21h_vect в сегменте cs
2) двойное слово Int_21h_vect, в котором хранится длинный адрес предыдущего обработчика вектора 21h
3) сохранение смещения и сегмента в длинном указателе Int_21h_vect
Обратите внимание, что сама переменная описана, как dword, поэтому, чтобы записать туда слова, надо добавлять word ptr


Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 24.07.2017, 13:54

5
нет комментария
-----
Дата оценки: 24.07.2017, 14:20

Рейтинг ответа:

0

[подробно]

Сообщение
модераторам

Отправлять сообщения
модераторам могут
только участники портала.
ВОЙТИ НА ПОРТАЛ »
регистрация »

Мини-форум консультации № 191241

Зенченко Константин Николаевич
Модератор

ID: 31795

# 1

 +1 
 
= общий = | 24.07.2017, 13:45 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

Начнем с п.2.
Запись

Код (Assembler) :: выделить код
Int_21h_vect dd ?

равносильна записи
Код (Assembler) :: выделить код
Int_21h_vect dw ?;bx
             dw	?;es

в комментариях я написал, что куда будет записано в п.3

п.3
директива word ptr указывает компилятору, что код нужно создавать как будто переменная Int_21h_vect, не двойное слово, а слово. Если убрать эту директиву, компилятор выдаст ошибку "не соответствие типов(type mismatch)".

п.1.
Директива компилятору генерировать в коде длинный(far) переход, т.е. переход по адресу сегмент : смещение, которые хранятся в переменной Int_21h_vect. Или другими словами передать управление старому обработчику прерывания считанного перед этим, функцией 0х21/0х35

• Отредактировал: Зенченко Константин Николаевич (Модератор)
• Дата редактирования: 24.07.2017, 19:06

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 2

= общий = | 24.07.2017, 14:25 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

Все понятно?

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

Caesar
Посетитель

ID: 401251

# 3

= общий = | 24.07.2017, 14:48 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

В принципе понятно все, но нет уверенности в понимании!
Или не могу понять, что именно непонятно, т.е. сформулировать вопрос!
Как то так)))

1. После 1-го запуска программы, в переменной Int_21h_vect будет хранится адрес предыдущего обработчика (даже если это обработчик другой программы, значения не имеет)?
2. Если не будет происходить вызова нужного нам прерывания (т.е. на которое отреагирует программа) предыдущие обработчики будут меняться, это как-то отразиться в переменной или адрес измениться только при перехвате прерывания?
2. Каким образом попадет в эту переменную адрес следующего предыдущего обработчика при перехвате прерывания, если тот участок кода уже отработал и не был записан как резидент?
3.

Код (Assembler) :: выделить код
mov ax,2521h
mov dx, offset Int_21h_proc
int 21h

; теперь если какая нибудь прога вызовет 21 то сработает наш обработчик осталось завершить программу, 
; оставив ее резидентной в памяти (чтоб никто не затер наш обработчик) Иначе комп зависнет


Как это работает?

4. Как работает iret и в каких случаях ее применять

• Отредактировал: Caesar (Посетитель)
• Дата редактирования: 24.07.2017, 14:50

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 4

 +1 
 
= общий = | 24.07.2017, 15:13 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

© Цитата:
1. После 1-го запуска программы, в переменной Int_21h_vect будет хранится адрес предыдущего обработчика (даже если это обработчик другой программы, значения не имеет)?
Сам он там не появится. Его надо туда записать. Еще раз посмотрите мой ответ, как его туда записать
© Цитата:
2. Если не будет происходить вызова нужного нам прерывания (т.е. на которое отреагирует программа) предыдущие обработчики будут меняться, это как-то отразиться в переменной или адрес измениться только при перехвате прерывания?
Адреса предыдущего прерывания записывает в своем теле сама программа при перехвате прерывания. В принципе, конечно, вполне возможно, пробежаться по цепочке отработок и поменять тело чужой программы smile Но так никто не делает... Каждая программа отвечает только за свой код.
© Цитата:
3. Каким образом попадет в эту переменную адрес следующего предыдущего обработчика при перехвате прерывания, если тот участок кода уже отработал и не был записан как резидент?
Если программа перехватила отработку какого-то вектора и не является резидентов, то она обязана восстановить предыдущие вектора. Иначе, при последующем запуске какой-либо программы, отработка вектора скорее всего вызовет вылет, т.к. код, куда ссылается вектор уже неактуален.
Код (Assembler) :: выделить код
mov ax,2521h
mov dx, offset Int_21h_proc
int 21h
данный код устанавливает свой обработчик прерывания. В комментарии сказано примерно то же, что и я чуть выше.

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

Caesar
Посетитель

ID: 401251

# 5

= общий = | 24.07.2017, 15:18 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата: Лысков Игорь Витальевич
Сам он там не появится. Его надо туда записать. Еще раз посмотрите мой ответ, как его туда записать
я это и имел в виду))
smile smile smile
Спасибо, помогли разобраться.

Зенченко Константин Николаевич
Модератор

ID: 31795

# 6

= общий = | 24.07.2017, 15:30 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

Все несколько не так.
Представьте, что в памяти есть таблица векторов 0х0000 : 0х0400, всего 256 прерываний, на каждое прерывание 4-е байта. Когда программа ставит свой обработчик, она должна прочитать адрес старого обработчика, запомнить его и в таблицу прерываний записать сегмент : смещение своего обработчика.
Судя по вопросу Вы медленно подходите к гл.10, если уже не там.
В этой главе рассматриваются резиденты. Смысл их - программа запустилась, отработала, поставив свой обработчик, завершилась, оставшись резидентной. После этого запускается другая программа и к примеру пытается вывести строку, функцией 9, прерывания 21. Наш резидентный обработчик, получает управление, т.к. его сегмент : смещение записаны в таблице векторов и именно ему система передаст управление, когда будет вызвано прерывание 21, проверив содержимое регистра АН, если там нужное нам значение(9), мы как бы перехватываем этот вызов, делаем, что нам нужно и все, если значение не совпадает, то просто передает управление обработчику, который был до нашего резидента и так будет продолжатся, пока по всей цепочке не спустимся в недра ОСи и не будет вызван системный обработчик прерывания.

iret аналогичен retf, но он еще восстанавливает и регистр флагов. Это связано с тем, что механизм прерываний аналогичен как для программных, так и для аппаратных. С той лишь разницей, что аппаратные прерывания могут наступить в любой момент и прервать любую программу и если он нарушит, какой либо флаг, то прерванная программа может не правильно работать.

Caesar
Посетитель

ID: 401251

# 7

= общий = | 24.07.2017, 15:33 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата: Зенченко Константин Николаевич
Судя по вопросу Вы медленно подходите к гл.10, если уже не там.
вот я ее закончил, теперь пора вопросов))

Зенченко Константин Николаевич
Модератор

ID: 31795

# 8

= общий = | 24.07.2017, 15:37 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

© Цитата: Caesar
теперь пора вопросов

smile
И где они?

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 9

= общий = | 24.07.2017, 15:39 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

Не заметил

© Цитата:
4. Как работает iret и в каких случаях ее применять

Есть два способа вызова подпрограмм: с помощью call и с помощью int
Call, в свою очередь, может быть коротким и длинным

Короткий call - это вызов в текущем сегменте,
в стек заносится смещение следующей команды за call
текущим адресом становится смещение подпрограммы
После завершении подпрограммы при помощи ret из стека извлекается адрес следующей
команды и заносится в текущий адрес.

Длинный call усложняется тем, что в стек заносится длинный указатель, т.е. сегмент:смещение
Передается управление в новые сегмент:смещение, которые берутся из кода команды
Т.е. вызывается подпрограмма из другого сегмента.
После завершении подпрограммы при помощи retf из стека извлекается длинный указатель следующей
команды и мы оказываемся за командой call.

Прерывания бывают двух типов: аппаратные и программные. Аппаратные, например, клавиатуры или таймер,
вызываются автоматически по соответствующему событию. Программные, например, int 21h вызываются явно.
И те, и те, работают одинаково. В принципе, и аппаратное прерывание можно вызвать явно, но, обычно,
это не имеет смысла. Из-за того, что прерывания, особенно аппаратные, вызываются в любой момент времени,
необходимо еще сохранять флажки, регистр FLAGS. Команда int это делает автоматически. Сам вызов отработчика похож на дальний вызов.

Т.о., перед вызовом прерывания (любым способом) в стек заносятся флажки, сегмент, смещение.
Выход из прерывания осуществляется командой iret, которая извлекает из стека эти три слова,
восстанавливает флажки и делает длинный переход.

Если известен адрес вектора, то можно вызвать отработчик прерывания и длинным вызовом call, но перед вызовом call
необходимо дать команду pushf (сымитировать вызов по int), чтобы iret корректно завершило отработку обработчика прерывания.

Если сказать проще: прерывания должны заканчиваться iret, обычные подпрограммы ret или retf, в зависимости от способа вызова. smile

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

• Отредактировал: Лысков Игорь Витальевич (Старший модератор)
• Дата редактирования: 24.07.2017, 15:45

Caesar
Посетитель

ID: 401251

# 10

= общий = | 24.07.2017, 15:45 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

несколько уже были))

© Цитата: Caesar
В принципе понятно все, но нет уверенности в понимании!
Или не могу понять, что именно непонятно, т.е. сформулировать вопрос!
Как то так)))

smile smile smile

Кроме аппаратных, программных есть еще и системные прерывания?

Я понял! В таблице векторов прерываний мы осуществляем подмену адреса прерывания
Код (Assembler) :: выделить код
mov ax,2521h
mov dx, offset Int_21h_proc 
int 21h

на свой адрес и "дорабатываем" или не дорабатываем прерывание.

Я не пойму того как адрес предыдущего обработчика, попадает в переменную Int_21h_vect, когда программа уже висит в памяти,
ведь участок кода, который отвечал за загрузку адреса в эту переменную
Код (Assembler) :: выделить код
mov ah, 35h 
mov al,21h 
int 21h

mov word ptr Int_21h_vect, bx
mov word ptr Int_21h_vect+2, es

уже отработал, при первом запуске, а в участок программы, который стал резидентом он не попадает?

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 11

= общий = | 24.07.2017, 15:56 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

Так код отработал. Получил адрес вектора и записал в длинном указателе, который находится в участке кода,
который остается резидентным. А больше этот код не нужен. Адрес предыдущего обработчика мы получаем только один раз, при запуске программы.

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

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 12

= общий = | 24.07.2017, 15:59 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

© Цитата:
Кроме аппаратных, программных есть еще и системные прерывания?
Есть только аппаратные и программные прерывания.
Система пользуется теми же самыми прерываниями.

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

Зенченко Константин Николаевич
Модератор

ID: 31795

# 13

= общий = | 24.07.2017, 16:22 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

© Цитата: Caesar
Я не пойму того как адрес предыдущего обработчика, попадает в переменную Int_21h_vect, когда программа уже висит в памяти, ведь участок кода, который отвечал за загрузку адреса в эту переменную уже отработал


При написании резидентов, есть код настройки и код резидента. После выполнения прерывания 27 с параметром Init:, все что ниже этой метки будет отброшено(т.е. код настройки), а память будет помечена как свободная.
Переменная Int_21h_vect, с записанными значениями адреса старого обработчика, расположена в резидентной части и отброшена не будет, так и останется в памяти. Именно от туда и будет читаться адрес старого обработчика.

Caesar
Посетитель

ID: 401251

# 14

= общий = | 24.07.2017, 19:53 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

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

-----
 Прикрепленный файл (кликните по картинке для увеличения):

Caesar
Посетитель

ID: 401251

# 15

= общий = | 25.07.2017, 07:02 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата: Зенченко Константин Николаевич
адрес старого обработчика.
т.е. оригинального?

Зенченко Константин Николаевич
Модератор

ID: 31795

# 16

 +1 
 
= общий = | 25.07.2017, 09:41 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Caesar:

Последовательность расположения обработчиков в памяти будет иметь такой вид:


При запуске системы, ОСь поставит свой обработчик. Каждый раз, при установке нового обработчика, в таблице векторов будет записан новый адрес обработчика и запомнен адрес старого.

Как уже Вам сказали:

© Цитата: Лысков Игорь Витальевич
В принципе, конечно, вполне возможно, пробежаться по цепочке отработок

в поисках оп.кодов команд CALL FAR или JMP FAR, после которых будет находится адрес предыдущего обработчика и спустится в саму ОСь. Но это только в теории, и только в ручном режиме. Правила написания резидентов как бы есть, но им не всегда следуют отдельные "клоуны".
smile

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 17

 +1 
 
= общий = | 25.07.2017, 10:33 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Зенченко Константин Николаевич:

© Цитата:
в поисках оп.кодов команд CALL FAR или JMP FAR
Более надежно прошагать до сегмента ОС. smile
Когда-то развлекался подобным... smile
Т.к. код вполне можно построить динамически, т.е. сформировать команду перехода по ходу дела...
На "правильный" код не стоит рассчитывать...

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

Зенченко Константин Николаевич
Модератор

ID: 31795

# 18

 +2 
 
= общий = | 25.07.2017, 11:12 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:

© Цитата: Лысков Игорь Витальевич
На "правильный" код не стоит рассчитывать.

smile
Я как раз и говорил, сам вопрос спуска в ОСь скорее теоретический, и только в ручном режиме.
© Цитата: Лысков Игорь Витальевич
Более надежно прошагать до сегмента ОС

Сегмент ОСи, можно из PSP выловить, там как раз есть альтернативный обработчик 0х21.
smile

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 19

= общий = | 25.07.2017, 12:54 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Зенченко Константин Николаевич:

Да возможностей определить сегмент ОС масса.
Например, можно найти список сегментов.

=====
Каждый выбирает по себе -
Щит и латы, посох и заплаты.
Меру окончательной расплаты
Каждый выбирает для себя.

 

Возможность оставлять сообщения в мини-форумах консультаций доступна только после входа в систему.
Воспользуйтесь кнопкой входа вверху страницы, если Вы зарегистрированы или пройдите простую процедуру регистрации на Портале.

Яндекс Rambler's Top100

главная страница | поддержка | задать вопрос

Время генерирования страницы: 0.15853 сек.

© 2001-2017, Портал RFPRO.RU, Россия
Авторское право: ООО "Мастер-Эксперт Про"
Калашников О.А.  |  Гладенюк А.Г.
Версия системы: 7.41 от 25.02.2017
Бесплатные консультации онлайн