Консультация № 144969
25.09.2008, 09:43
0.00 руб.
0 6 1
Уважаемые эксперты помогите решить следующую задачу. Нужно сделать резидент который бы перехватывал бы ДОС прерывание «вывод строки на экран» и копировал эту строку в файл. Я тут начал это делать но столкнулся с проблемой я не могу использовать прерывания в резиденте так как сам их перехватываю. И не уверен что
правильно определил по какому адресу находится строка. Пожалуйста доведите мою программу до ума.


Приложение:
.286
.model tiny
.code
My_string db 'c:\123.txt$' ; д ©« ¤«п § ЇЁбЁ
My_string1 dw 40 dup(?) ; ЃгдҐа ¤«п б®еа ­Ґ­Ёп бва®ЄЁ
Handle dw 0 ; yandl д ©« 
Adres dw 0 ;  ¤аҐб бва®ЄЁ
ORG 100h
start:
jmp setup ; ЏҐаҐ©¤Ґ¬ Є Їа®Ја ¬¬Ґ Ёбв ««пжЁЁ
; ђҐ§Ё¤Ґвп з бвм Їа®Ја¬¬л зЁв Ґвбп §¤Ґбм-----------------------------------------------------------------------------
int9_handler PROC FAR
cmp ah,9 ;Џа®ўҐаЁ¬: нв® дгЄжЁп 09h?
je Ok_09 ;…б«Ё в Є, в® ¬ҐвЄг Ok_09
jmp qwe5 ;…б«Ё Ґв в® ЁбЇ®«м§гҐ¬ бв ал© ўҐЄв®а ЇаҐалў Ёп
Ok_09:
pushf ; ‘®еа Ё¬ ॣЁбва д« Ј®ў
pusha
; c®еа ­Ё¬ бва®Єг ў ЎгдҐаҐ My_string1
push ds
push cs ;Ђ¤аҐб бва®ЄЁ ¤®«¦Ґ­ Ўлвм ў DS:DX
pop ds
mov cx,40 ; гбв ­®ўЁ¬ бзҐвзЁЄ
mov si,0 ; Ё­¤ҐЄб  ¤аҐб  ­  ­®«м
lea BX, My_string1 ; ў Bx  ¤аҐб ЎгдҐа 
mov Adres, dx ;  ¤аҐб бва®ЄЁ ў DX
poperlo: ; жЁЄ« Є®ЇЁа®ў ­Ёп ў ЎгдҐа
mov ax,[adres+si] ; ў  е 2 бЁ¬ў®«  Ё§ бва®ЄЁ
MOV WORD PTR [BX], ax ; ў ЎгдҐа 2 бЁ¬ў®« 
inc bx ; Є б«Ґ¤гойЁ¬
inc bx ; 2 Ў ©в ¬
inc si
inc si
loop poperlo
pop ds ;ў®бв ­®ўЁ¬ DS
;®вЄалў Ґ¬ д ©« ¤«п §aЇЁбЁ
mov ax,3d02h ;ЋвЄалў Ґ¬ д ©« ¤«п звҐЁп Ё § ЇЁбЁ
mov dx,offset My_string ;?¬п ®вЄалў Ґ¬®Ј® д ©« ў DX
int 21
mov HANDLE,AX ;б®еа­Ё¬ ­®¬Ґа д ©« 
mov ax,4200h ;“бв ­®®ўЁ¬ гЄ § вҐ«м ­  Є®Ґж д ©« 
mov al,02h ;
xor cx,cx ;ЋЎг«Ё¬ ॣЁбвал
xor dx,dx ;
MOV BX,HANDLE
int 21
; § ЇЁбм ў д ©«
mov ah,40h ;‡ ЇЁиҐ¬ ў д ©« Є®¤ ¤«Ё®©
mov cx,80 ; 80 бЁ¬ў®«®ў
lea dx, My_string1 ; ЎгдҐа ®вЄг¤ ў®§м¬Ґ¬ еў®бв
int 21
;§ Єа®Ґ¬ д ©« ¤«п з⥨п
mov ah,3Eh ;‡ § Єа뢥¬ дa©«
MOV BX,HANDLE ;Ќ®¬Ґа дa©«a
int 21
popa
popf
qwe5:
jmp cs:[old_interrupt9] ; ЏҐаҐ©¤Ґ¬ Є бвa஬㠮Ўа Ў®взЁЄг INT 09h
old_interrupt9 DWORD ?
int9_handler ENDP
end_ISR label BYTE
; ------------- (Љ®Ґж १Ё¤Ґв®© з бвЁ Їа®Ја ¬¬л) --------------------------------------------------
setup:
mov ax,3521h ; ЋЇаҐ¤Ґ«Ё¬ §­ зҐЁҐ бв а®Ј® ўҐЄв®а INT 09h
int 21h
mov word ptr old_interrupt9,bx ; ‘®еа­Ё¬ ҐЈ® ў ЇҐаҐ¬Ґ®©
mov word ptr old_interrupt9+2,es
mov ax,2521h ; “бв ­®ўЁ¬ ­®ўл© ўҐЄв®а ЇаҐалў ­Ёп INT 09h
mov dx,offset int9_handler
int 21h
mov ax,3100h ; ‡ ўҐаиЁ¬ Їа®Ја ¬¬г Ё ®бв ўЁ¬ ҐҐ з бвм १Ё¤Ґв® ў Ї ¬пвЁ
mov dx,OFFSET end_ISR ; ‘¬ҐйҐЁҐ Є®­ж  १Ё¤Ґв®© з бвЁ
mov cl,4
shr dx,cl ; Џ®¤Ґ«Ё¬ ҐЈ® ­  16, зв®Ўл г§­ вм ¤«Ёг ў ЇaаaЈаaдaе
inc dx ; ЋЄагЈ«Ё¬ зЁб«® Ї а Ја д®ў ў Ў®«миго бв®а®г
int 21h
END start

Обсуждение

давно
Старший Модератор
31795
6196
25.09.2008, 12:49
общий
это ответ
Здравствуйте, Sergik1977!

Программа в приложении.
Адрес строки у Вас уже есть в паре регистров DS:DX.
Неизвестно только длина строки, которая ограничена символом '$'.
Именно поэтому копирование в строки в буфер лишнее, т.к. она может быть очень большой, а это может привести к сбою в работе Вашего резидента.
Удачи!

Приложение:
.286
.model tiny
.code
ORG 100h
start:
jmp setup; Перейдем к программе исталляции
; Резидетя часть прогрммы начитается здесь
My_string db 'c:\123.txt',0; файл для записии
Handle dw ?;handl файла
new21 PROC FAR
cmp ah,9;Проверим: это фукция 09h?
je Ok_09;Если т к, то метку Ok_09
db 0eah
old21h_o dw ?
old21h_s dw ?
;обработчик
Ok_09:
pushf;Сохраним регистр флагов
pusha
;запоминаем адрес строки
push ds
push dx
;определяем длину строки
mov si,dx
xor cx,cx
cld
;поиск символа "$"
CheckString: lodsb
inc cx
cmp al,'$'
jnz CheckString
;заопминаем длину строки
push cx;save string length
переходим в свой сегмент данных
push cs
pop ds
;открываем файл для зaписи
mov ax,3d02h;Открыв ем ф йл для чтеия и з писи
mov dx,offset My_string;Имя открыв емого ф йл в DX
;аналог INT 21h
pushf
call dword ptr cs:[old21h_o]
;устанавливаем указатель в конец файла
mov HANDLE,AX;сохрним номер файла
mov bx,ax
mov ax,4202h;Устаноовим указатель на коец файла
xor cx,cx;Оиулим регистры
xor dx,dx
;аналог INT 21h
pushf
call dword ptr cs:[old21h_o]
;запись в файл
mov ah,40h;Запишем в файл код длиой
mov bx,HANDLE
;востановим длину строки и её адрес
pop cx
pop dx
pop ds
;аналог INT 21h
pushf
call dword ptr cs:[old21h_o]
;переходим на свой сегмент
push ds
push cs
pop ds
mov ah,3Eh; закрывем фaйл
MOV BX,HANDLE;Номер фaйлa
;аналог INT 21h
pushf
call dword ptr cs:[old21h_o]
;востанавливаем регистры и возвращаемся в старый обработчик
pop ds
popa
popf
jmp dword ptr cs:[old21h_o]
new21 ENDP
;------------- (Коец резидетой части программы)
setup:
mov ax,3521h; Определим значеие старого вектор INT 21h
int 21h
mov old21h_o,bx;Сохрним его в перемеой
mov old21h_s,es
mov ax,2521h;Установим новый вектор прерывания INT 21h
mov dx,offset new21
int 21h
;оставить резидентной
mov dx,offset setup
int 27h
END start
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
25.09.2008, 13:29
общий
Спасибо огромное Константин Николаевич программа работает как задумано. Извините за назойливость, но я не понял пару моментов. Это касается инициализации переменных. Почему эти строчки стоят
до процедуры «new21»
My_string db 'c:\123.txt',0
Handle dw ?
А эти в теле процедуры:
db 0eah
old21h_o dw ?
old21h_s dw ?
И мне непонятно назначение вот этого байта без имени «db 0eah»
И непонятно зачем мы сохраняем флаги
pushf
call dword ptr cs:[old21h_o]
но не восстанавливаем их потом?
Конечно я могу обшарить кучу справочников и найти ответы на эти вопросы,
Но у меня маленький сын на руках и не дает мне достаточного времени.

давно
Старший Модератор
31795
6196
25.09.2008, 13:53
общий
Строки с указанием имени файла и указатель на открытый файл являются даными и должны находится вне исполняемого кода.

Загадочное db 0eah , это опкод команды jmp far сегмент:смещение являются не данными, а кодом.
Такой подход позволяет экономить 4-е байта на хранении адреса старого обработчика, нужных для резидентных программ.

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

Неизвестный
25.09.2008, 15:01
общий
Поражаюсь как люди пишут красиво программу. Я как напишу так там одни переходы через всю программу. Ну на последних два вопроса Константин Николаевич. Почему открывали файл и записывали в сегменте перехваченной программы а закрыли файл в своем сегменте? Или это просто так получилось? И я так и не понял почему вот эти данные old21h_o dw ?
old21h_s dw ? нельзя вынести из тела процедуры. Я попытплся это сделать резидент перестал работать)))

давно
Старший Модератор
31795
6196
25.09.2008, 15:32
общий
Чтобы вынести эти строки за пределы резидента Вам нужно изменить так часть программы:
Код:
 jmp   setup; Перейдем к программе исталляции
; Резидетя часть прогрммы начитается здесь
My_string db 'c:\123.txt',0; файл для записии
Handle dw ?;handl файла
old21h_o dw ?
old21h_s dw ?
new21 PROC FAR
cmp ah,9;Проверим: это фукция 09h?
je Ok_09;Если т к, то метку Ok_09
jmp dword ptr cs:[old21h_o]
;обработчик


Файл открывали в сегменте резидента:
Код:
 ;переходим в свой сегмент данных
push cs
pop ds

В сегменте программы только записывали в файл. Адреса имени файла и блока записи(чтения) адресуются по умолчанию DS:DX.
B принципе сегментным регистром можно было и не игратся только в нужных местах постоянно добавлять сегмент кода CS:.
Мне кажется так код проще смотрится.

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

Неизвестный
25.09.2008, 16:11
общий
Еще раз спасибо. Все стало понятно.
Форма ответа