Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.01.2015, 11:46   #1
Berlioz
Изучающий C и ASM
Пользователь
 
Регистрация: 25.05.2012
Сообщений: 89
Вопрос Установка обработчика прерывания

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

Подскажите, пожалуйста, почему следующий код не работает. Вроде бы все правильно написал. Синтаксис FASM
Код:
;инициализация
;...

jmp start

text db 0x80,0x81,0x82,0x83,0x84,0x85,'$'
font:
file '866-8x14.bin'

start:
	push es
           ;код русификации экрана. Вырезан из-за размера
           ;...
	push 0
	pop es

	;записываем код обработчика в ничейную область по адресу
           ;0000:01E0
           mov cx,interr_size
	mov si,interr
	mov di,0x01e0
	@@:
	mov al,byte[ds:si]
	mov byte[es:di],al
	inc si
	inc di
	loop @b

	;замена прерывания на свое
           cli
	push si
	mov si,[es:0xBE];прерывание мультиплексора. Без DOS оно пустует
	mov [o_seg],si
	mov [es:si],word 0
	mov si,[es:0xBC]
	mov [o_off],si
	mov [es:si],word 0x01E0
	pop si
	pop es
	sti

	mov ah,12h
	int 0x2f
	
interr:
	push ax
           mov ax,0x01E0
	mov ds,ax
           pop ax
	jmp short @f
	o_seg rw 1
	o_off rw 1
	@@:
		cmp ah,12h
		jne @f
		push es
		push 0x0B800
		pop es
		push di
		;xor di,di
		mov di,160*4
		mov ah,'T'
		mov al,0xA
		stosb
		xchg ah,al
		stosb
		xchg ah,al
		stosb
		xchg ah,al
		stosb
		pop di
		pop es
	@@:
		mov es,[o_seg]
		jmp [es:o_off]; дальше по прерыванию

interr_size = $-interr
Berlioz вне форума Ответить с цитированием
Старый 11.01.2015, 21:46   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

А регистр DS кто сохранять будет?

Зачем делатся mov [es:si],word 0 при "перехвате" прерывания? SI как бы указывает на смещение обработчика, но на что указывает ES? Вы пытаетесь изменить адрес вектора прерывания или сам код обработчика, а то ни то ни это...

Для копирования блока памяти легче использовать LODSB/STOSB вместо MOV/INC.
waleri вне форума Ответить с цитированием
Старый 12.01.2015, 19:22   #3
Berlioz
Изучающий C и ASM
Пользователь
 
Регистрация: 25.05.2012
Сообщений: 89
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
А регистр DS кто сохранять будет?
Виноват!

Цитата:
Зачем делатся mov [es:si],word 0 при "перехвате" прерывания?
Опечтка в коде. Заменил на
Код:
mov si,[es:0xBE];прерывание мультиплексора. Без DOS оно пустует
mov [o_seg],si
mov [es:0xBE],word 0
mov si,[es:0xBC]
mov [o_off],si
mov [es:0xBC],word 0x01E0
Код загрузки обработчика в память переписал на
Код:
mov cx,interr_size
mov si,interr;
mov di,0x01e0 ;es=0
cld
rep movsb
Теперь столкнулся с тем, что код просто зависает на вызове прерывания. Чего я еще не учел?
Berlioz вне форума Ответить с цитированием
Старый 12.01.2015, 20:57   #4
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

jmp в конце должен быть FAR.
Если опять не работает, тогда убирайте все лишнее и возвращайте постепенно и смотрите на каком шаге сломается
waleri вне форума Ответить с цитированием
Старый 13.01.2015, 14:30   #5
Berlioz
Изучающий C и ASM
Пользователь
 
Регистрация: 25.05.2012
Сообщений: 89
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
jmp в конце должен быть FAR.
Если опять не работает, тогда убирайте все лишнее и возвращайте постепенно и смотрите на каком шаге сломается
Код переписал на вот такой. Теперь перехваченное прерывание отрабатывает, но зависание на дальнем возврате (jmp far).
Код:
mov cx,interr_size
mov si,interr
mov di,0x01e0
cld
rep movsb

cli
push si
mov si,[es:0xBE];seg
mov word[o_seg],si
mov [es:0xBE],word 0
mov si,[es:0xBC];off
mov word[o_off],si
mov [es:0xBC],word 0x01E0
pop si
pop es
sti

mov ax,1687h
int 0x2f
mov ax,0x4C00
int 0x21 ;отлаживаю из-под DOS, т.к. надоело флешку дергать
call interr;для дизассемблера, чтобы показывал код обработчика
jmp interr;туда же

interr:
db 68; опкод команды push
o_seg:
         dw 0
db 68
o_off:
        dw 0
cmp ax,1687h
jne @f
push es
push 0x0B800
pop es
push di
mov di,80*2*4
mov al,'T'
mov ah,0xA
stosb
xchg ah,al
stosb
xchg ah,al
stosb
xchg ah,al
stosb
pop di
pop es
@@:
retf
interr_size = $-interr
P.S. У меня уже мысль, что надо поменять местами байты в значениях o_off и o_seg, но не думаю, что это даст что-то полезное
UPD: Если убрать упоминание про возврат (db 68 и почие) и поставить в конец не retf, а iret, то все прекрасно работает

Последний раз редактировалось Berlioz; 13.01.2015 в 16:44.
Berlioz вне форума Ответить с цитированием
Старый 13.01.2015, 16:54   #6
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Из прерываний выходят через iret
waleri вне форума Ответить с цитированием
Старый 13.01.2015, 19:12   #7
Berlioz
Изучающий C и ASM
Пользователь
 
Регистрация: 25.05.2012
Сообщений: 89
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Из прерываний выходят через iret
iret у меня работает. Однако при тестировании под DOS еще надо было учесть, что в памяти "висит" DPMI (с которого запускается FASMD, функция 1678h), соответственно, надо было дальше передать "эстафету". Вот я и пытаюсь понять, где косяк
Может надо было не retf юзать, а опкод jmp far (с другой стороны, в MBR Win7 используется этот трюк)? Я уже вроде все перепробовал.

P.S. Сижу уже как истукан
Berlioz вне форума Ответить с цитированием
Старый 13.01.2015, 22:47   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

да, для вызова оригинала надо jmp far, только надо все регистры сохранить, а это может быть проблемой - вам нужен DS или ES чтоб добраться до адреса оригинального обработчика.
Самый простой способ - сохранять адрес прямо в конце обработчика и использовать инструкцию jmp far 0:0 (вместо jmp far [adr]);
waleri вне форума Ответить с цитированием
Старый 17.01.2015, 20:34   #9
Berlioz
Изучающий C и ASM
Пользователь
 
Регистрация: 25.05.2012
Сообщений: 89
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Самый простой способ - сохранять адрес прямо в конце обработчика и использовать инструкцию jmp far 0:0 (вместо jmp far [adr]);
Можно по-подробней?
P.S. Я использовал следующий код, но он тоже не работал. Не могу понять, что опять не так
Код:
interr:
cmp ax,1687h
jne @f
push es
push 0x0B800
pop es
push di
mov di,80*2*4
push ax
mov al,'T'
mov ah,0xA
stosb
xchg ah,al
stosb
xchg ah,al
stosb
xchg ah,al
stosb
pop ax
pop di
pop es
@@:
db 0xEA ;jmp far 0:0. Сначала пишется смещение, затем сегмент (в машинных кодах)
o_off: dw 0 ; проверено связкой FASM+Winhex
o_seg: dw 0 ; код загрузки обработчика и сохранения старого адреса не менял
interr_size = $-interr

Последний раз редактировалось Berlioz; 17.01.2015 в 20:43.
Berlioz вне форума Ответить с цитированием
Старый 17.01.2015, 22:09   #10
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Ну это надо уже отладчиком смотреть.
Кстати, есть инструкция stosw...
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Замена обработчика прерывания Berlioz Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 10.07.2014 15:35
Вызов обработчика событий Alex2009 Общие вопросы Delphi 6 16.03.2013 16:55
Изменение обработчика событий bogdan333 C++ Builder 10 29.04.2012 03:25
не получается установка обработчика закрытия формы sergey113 Помощь студентам 2 14.09.2008 16:00