Консультация № 193379
09.06.2018, 01:28
0.00 руб.
1 2 1
Здравствуйте! Прошу помощи в следующем вопросе:

При написании резидента по книжке Олега Калашникова, не могу понять один момент. В Книге что таблица вектора прерываний в MS-DOS находится в сегменте 0000.
Через отладчик смотрю адрес прерывания 21h по адресу 0000:084 (21h * 4 = 84h). В таблице видно, что адрес 21h -го прерывания располагается по F000:14A0 (Показано на скриншоте в окне m2), но когда я пытаюсь сохранить этот адрес в переменные, или даже просто использую функцию 35h прерывания 21h, то функция выдает совершенно другие значения адреса (06С7:42B7 тоже на скриншоте показано в регистрах es:bx после выполнения ф-ции 35h). Т.е. почему то совсем другие значения чем в таблице по смещению 0000. И самое интересно, что когда я сохраняю эти полученные значения в переменные, а потом пытаюсь пригнуть по ним в обработчик (jmp dword ptr cs:[Var_Vector_Int21) то в отладчике видно, что на самом деле я перехожу по правильному адресу, вместо этих значений, которые сохранились в переменной и которые выдала 35h. Т.е. прыгая по сохраненному адресу 06С7:42B7 на самом деле я прыгнул на правильный адрес, на F000:14A0. Не могу понять как это происходит, может это из-за отладчика проскакивают такие странные значения или все таки я что то упустил?

Приложение:
.286
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
Begin_Resident:

;Идем на инициализацию
jmp Label_ResidentBegin

;---------------------------PROCEDURES--------------------------

;Обработчик прерывания 21h--------------
proc_Int21_Stub proc
;---Проверяем эхо
cmp ax,8899h
jnz Label_To_Original_Vector

;---Уходим в оригинальный обработчик
Label_To_Original_Vector:
jmp dword ptr cs:[Var_Vector_Int21]
proc_Int21_Stub endp

;---------------------------PROCEDURES--------------------------

;----------------------------VARIABLES--------------------------

Var_Vector_Int21 dd 0

;--------------------------END VARIABLES------------------------

;Инициализация резидента
Label_ResidentBegin:
;---Проверяем наличие резидента в памяти
mov ax,8899h
int 21h
cmp ax,9988h
jz Label_ExitResident

;---Если резидента в памяти нету, находим адрес оригинального обработчика прерывания 21h
mov ah,35h
mov al,21h
int 21h
mov word ptr [Var_Vector_Int21],bx
mov word ptr [Var_Vector_Int21+2],es

;---Устанавливаем новый вектор прерывания 21h
mov ah,25h
mov al,21h
mov dx,offset proc_Int21_Stub
int 21h

;TEST
mov ah,09h
mov dx,offset T
int 21h
T db 'TEST$'

;Выход из резидента
Label_ExitResident:
int 20h

CSEG ends
end Begin_Resident
Прикрепленные файлы:
a7e50b1cde3d4b91f45768ec2637912b9d52a835.JPG

Обсуждение

давно
Старший Модератор
31795
6196
10.06.2018, 13:55
общий
10.06.2018, 14:09
Адресаты:
Цитата: i.am.krepkov.ivan
Не могу понять как это происходит, может это из-за отладчика проскакивают такие странные значения или все таки я что то упустил?

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

Набросал код
[code lang=asm]model tiny
.code
org 100h
begin: mov ah,3ch
xor cx,cx
lea dx,dbFile
int 21h
mov di,ax
mov ah,40h
mov bx,di
mov cx,400h
xor dx,dx
mov ds,dx
int 21h
mov ah,3eh
mov bx,di
int 21h
ret
dbFile db 'dump400.bin',0
end begin[/code]

И запстил в чистой ОСи и отладчике:
Дамп чистой ОСи


И дамп отладчика


И еще дамп отладчика под отладчиком.



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

давно
Старший Модератор
31795
6196
12.06.2018, 15:08
общий
это ответ
Здравствуйте, i.am.krepkov.ivan!

Принципы работы отладчиков, как раз касаются изучаемой Вами темы. Разные отладчики работают по разному, одни подменяют первый байт инструкции на 0C3h(int 3), и потом обрабатывают прерывание, другие эмулируют код программы. Каждый раз прерывая программу, отладчик сохраняет все регистры, обрабатывает состояние: выводит состояние памяти и регистров и т.д., когда обработка завершается, отладчик восстанавливает все регистры и все начинается заново. Если сработало прерывание, которое перехватил отладчик, он проверяет его, если это его касается- обрабатывает, если нет передает управление предыдущему обработчику, это есть у Вас в коде:
[code lang=asm]
proc_Int21_Stub proc
;---Проверяем эхо
cmp ax,8899h
jnz Label_To_Original_Vector
;---Уходим в оригинальный обработчик
Label_To_Original_Vector:
jmp dword ptr cs:[Var_Vector_Int21]
proc_Int21_Stub endp[/code]
Именно это и произошло в данном случае, попав на прерывание, которое обрабатывает отладчик, значение адреса было подменено отладчиком(он не хочет, и не будет сам себя отлаживать) и передано управление старому обработчику.

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

Форма ответа