Консультация № 201516
15.10.2021, 22:37
0.00 руб.
0 6 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Не могу разобраться как работает резидентная программа по книге Калашникова, помогите пожалуйста
Код:

CSEG segment
assume cs:CSEG,es:CSEG,ds:CSEG,ss:CSEG
org 100h
Start:
jmp Init
Int_21h_proc proc
cmp ah,9
je Ok_09

jmp dword ptr cs:[Int_21h_vect]

Ok_09:
push ds
push dx
push cs
pop ds
mov dx,offset My_stirng
pushf
call dword ptr cs:[Int_21h_vect]

pop dx
pop ds
iret
Int_21h_vect dd ?

My_stirng db 'Moya stroka!$'
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 ax,2521h
mov dx,offset Int_21h_proc
int 21h

mov dx,offset Init
int 27h
CSEG ends
end Start

И так, как я понимаю:
1. Получаем адрес оригинального прерывания и сохраняем его сегмент и смещение в переменную Int_21h_vect
2. Загружаем адрес нашего обработчика, вместо оригинального. То есть мы не изменяем адрес как таковой оригинального обработчика, а изменяем адрес указывающий на него в таблице векторов. Таблица векторов это номера прерываний, указывающие где находиться это прерывание в памяти.
Далее мне не понятно следующее:
1.
Код:
jmp dword ptr cs:[Int_21h_vect]

Я понимаю зачем в одном случае мы используем jmp, а в другом call. Так как в одном случае нам нужно просто отдать работу оригинального обработчика, а в другом вернуться, чтобы восстановить регистры.
Я не понимаю, что значит cs:[Int_21h_vect]. в Переменной и так храниться сегмент и смещение, зачем нам ещё раз указывать сегмент cs, который указывает на сегмент кода резидентной программы. Как вообще происходит прыжок если по сути указывается 2 сегмента и смещение.
2.
Код:
	
push cs
pop ds
mov dx,offset My_stirng

Когда мы находимся в контрольной программе для проверки работы обработчика, при его вызове мы переходим на сегмент кода обработчика, остальные же сегментные регистры не изменяются и чтобы подменить исходную строку на нашу, мы подменяет сегмент данных контрольной программы, на сегмент кода резидентной для того чтобы подменить адрес исходной строки на нашу ( то что все сегменты находятся на одном адресе у com программ я помню). Мне не понятно зачем сохранять а затем восстанавливать после работа оригинального прерывания в стеке другие регистры, если они не изменяются.
Код:

push ds
push dx
pop dx
pop ds

Остальное же мне вроде все понятно, Огромное спасибо вам

Обсуждение

давно
Посетитель
405378
6
15.10.2021, 22:50
общий
1.
Код:
jmp dword ptr cs:[Int_21h_vect]


Я понимаю зачем в одном случае мы используем jmp, а в другом call. Так как в одном случае нам нужно просто отдать работу оригинального обработчика, а в другом вернуться, чтобы восстановить регистры.
Я не понимаю, что значит cs:[Int_21h_vect]. в Переменной и так храниться сегмент и смещение, зачем нам ещё раз указывать сегмент cs, который указывает на сегмент кода резидентной программы. Как вообще происходит прыжок если по сути указывается 2 сегмента и смещение.

Вы не поверите, когда отправил вопрос, мне тут же пришел ответ в голову.
Код:
jmp dword ptr cs:[Int_21h_vect]

Означает считать адрес по адресу и перейти по нему. То есть означает прочитай два "слова" по это адресу сегмент(cs):смещение(Int_21h_vect).
Только я все равно не понимаю, что значит квадратные скобки и как их можно использовать.
Код:
jmp dword ptr cs:[Int_21h_vect]

тоже самое как и
Код:
jmp dword ptr cs:Int_21h_vect
давно
Старший Модератор
31795
6196
18.10.2021, 10:39
общий
Адресаты:
Цитата: kolyatimushev
Только я все равно не понимаю, что значит квадратные скобки и как их можно использовать.

Это косвенная адресация. А значит - будет прочитано значение по адресу cs:Int_21h_vect и оно попадет CS : IP, т.е. будет сделан переход.

[code lang=asm]jmp dword ptr cs:Int_21h_vect[/code]
В синтаксисе MASM и TASM режиме совместимости с MASM(по умолчанию), это практически одно и тоже. Но если использовать другой компилятор FASM(к примеру) или TASM перевести в IDEAL, такой фокус уже не пройдет.

[code lang=asm]jmp dword ptr cs:Int_21h_vect = адрес
jmp dword ptr cs:[Int_21h_vect] = значенние по этому адресу[/code]

Цитата: kolyatimushev
Мне не понятно зачем сохранять а затем восстанавливать после работа оригинального прерывания в стеке другие регистры, если они не изменяются.

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

давно
Старший Модератор
31795
6196
18.10.2021, 10:57
общий
Адресаты:

Пример работы 211018t = контрольная программа
[code lang=asm]CSEG segment
assume cs:CSEG,es:CSEG,ds:CSEG,ss:CSEG
org 100h
Start:
mov ah,9
lea dx,dbHello
int 21h
ret
dbHello db 10,13,' Hello kolyatimushev:$'
CSEG ends
end Start[/code]
211018 - Обработчик из Вашего вопроса.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
405378
6
18.10.2021, 12:30
общий
Адресаты:
Спасибо, Константин. Теперь стало понятнее
давно
Старший Модератор
31795
6196
18.10.2021, 16:06
общий
Адресаты:
Для окончания понимания, пишем такой код:
[code lang=asm]model tiny
.code
org 100h
begin: jmp init
new21 proc
jmp dword ptr cs:[int21bx]
int21bx dw ?
int21es dw ?
new21 endp
init: mov ax,3521h
int 21h
mov int21bx,bx
mov int21es,es
push bx
push es
mov ah,09
lea dx,dbOldInt
int 21h
pop ax
call OutNum
mov al,':'
int 29h
pop ax
call OutNum
mov ah,09
lea dx,dbNewInt
int 21h
push cs
pop ax
call OutNum
mov al,':'
int 29h
lea dx,new21
mov ax,dx
call OutNum
mov ax,2521h
int 21h
lea dx,init
int 27h
dbNewInt db 10,13,'NewInt:=$'
dbOldInt db 10,13,'OldInt:=$'
OutNum: push dx
mov bx,10h
xor cx,cx
@@01: xor dx,dx
div bx
inc cx
push dx
or ax,ax
jnz @@01
@@02: pop ax
cmp al,10
jb @@03
add al,7
@@03: add al,'0'
int 29h
loop @@02
pop dx
ret
end begin[/code]
Компилируем его и запускаем два раза

1)
F000:14A0 - оригинальный обработчик Dos
0192:0103 - наш новый первый обработчик
2)
0192:0103 - наш новый первый обработчик(для второго запуска - оригинальный обработчик Dos)
01AE:0103 - наш новый второй обработчик
О том, что это наш обработчик, говорит одинаковое смещение в сегменте = 0103
Как-то так.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
20.10.2021, 10:48
общий
это ответ
Доброе время суток!

Цитата: kolyatimushev
Только я все равно не понимаю, что значит квадратные скобки и как их можно использовать.

Это косвенная адресация. А значит - будет прочитано значение по адресу cs:Int_21h_vect и оно попадет CS : IP, т.е. будет сделан переход.

[code lang=asm]jmp dword ptr cs:Int_21h_vect[/code]
В синтаксисе MASM и TASM режиме совместимости с MASM(по умолчанию), это практически одно и тоже. Но если использовать другой компилятор FASM(к примеру) или TASM перевести в IDEAL, такой фокус уже не пройдет.

[code lang=asm]jmp dword ptr cs:Int_21h_vect = адрес
jmp dword ptr cs:[Int_21h_vect] = значенние по этому адресу[/code]

Цитата: kolyatimushev
Мне не понятно зачем сохранять а затем восстанавливать после работа оригинального прерывания в стеке другие регистры, если они не изменяются.

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


Пример работы 211018t = контрольная программа
[code lang=asm]CSEG segment
assume cs:CSEG,es:CSEG,ds:CSEG,ss:CSEG
org 100h
Start:
mov ah,9
lea dx,dbHello
int 21h
ret
dbHello db 10,13,' Hello kolyatimushev:$'
CSEG ends
end Start[/code]
211018 - Обработчик из Вашего вопроса.

Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа