Привет всем. Тут такое дело - нужно перехватить Ctrl+Alt+Delete и запросить подтверждение на перезагрузку. Пробовал перехватавать int 19h - не работает почему-то, все перепроверил. Перехватываю int 9h - ловиться-то ловится, но вот при вызове внутри своего обработчика какого-либо другого прерывания (как call-ом, так и int-ом) начинаются какие-то непонятные зависания. Тестирую все это под Dos-ом на VMWare, так как Винда очень недоверчива к подобной комбинации. Посмотрите, плиз, код и укажите ошибки. Код (Text): .286 CSEG segment assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG org 100h start: jmp Init int9 proc pusha in al, 60h cmp al, 53h je @1 @2: popa jmp DWORD PTR cs:[ Old9 ] @1: push ds push 0h pop ds mov si, 417h mov ax, WORD PTR [si] pop ds and ax, 0Ch cmp ax, 0Ch jne @2 _exit: mov ah, 09h ; mov dx, cs ; mov ds, dx ; mov dx, offset mes ; pushf ; call DWORD PTR cs:[Old21] ; после этого int 21h - зависание mov al, 20h out 20h, al popa iret mes db 'C+A+D', 0dh, 0ah, '$' Old21 dd 0 Old9 dd 0 int9 endp Init: mov ax, 3509h int 21h mov WORD PTR [Old9], bx mov WORD PTR [Old9 + 2], es mov dx, cs mov ds, dx mov dx, offset int9 mov ax, 2509h int 21h mov ax, 3521h int 21h mov WORD PTR [Old21], bx mov WORD PTR [Old21 + 2], es mov dx, offset Init int 27h CSEG ends end start
Ну так я же вектор int 21h и не захватываю - даже если и так написать, то ничего хорошего не получится...
Уже пробовал )) А вообще, мне что-то кажется, что это Варины штучки, потому что подобные исходники, валяющиеся в сети так же себя ведут, то есть виснут. Почитав Зубкова, увидел что он там еще переключает клаву в конце своего обработчика. Попробовал - не работает... ))
bers Я про ДОС уже забываю, потихоньку. Придется поднять старые архивы. В понедельник может что-то подскажу...
внутри досявого обработчика поменьше мути с перехватом и вызовом, в мсдос есть проблема с реентерабельностью. даже и не вспомню щас чо там было то .....
bers Вот нашел фрагмент старой игрушки (обработчик 9-го прерывания) Код (Text): Int9 proc far push ax push cx push di push es in al, 60h mov ah, al in al, 61h or al, 80h out 61h, al and al, 7Fh out 61h, al mov al, ah cbw and al, 7Fh mov es, cs:DATSEG mov di, Offset es:KBDKEYS mov cx, es:[di-2] repne scasb sub di, (Offset es:KBDKEYS)+1 shl di, 1 jmp es:KBDPROC[di] EscKey: mov es:QUIT, 1 jmp short KBDRet FireKey: xor ah, FIRE jmp short SetKEY UpKey: xor ah, UP jmp short SetKEY LeftKey: xor ah, LEFT jmp short SetKEY RightKey: xor ah, RIGHT jmp short SetKEY DownKey: xor ah, DOWN SetKEY: and ah, ah jns Pressed and es:FLAGS, ah jmp short SetSCAN Pressed: or es:FLAGS, ah SetSCAN: mov es:SCAN, 0 and ah, ah js KBDRet mov es:SCAN, al KBDRet: pop es mov al, 20h out 20h, al pop di pop cx pop ax iret Int9 endp
CARDINAL правильно сказал - из обработчиков типа int 9 нельзя вызывать функции DOS... точнее, можно - но нужно проверять так называемый флаг занятости DOS (прочесть можно у Зубкова СВ). Еще есть такой прикол как текущий видеорежим. А что если я из игры Lines нажму три клавиши ?
Самое интересное то, что если я, скажем, вывожу строку на экран 9-ой функцией int 21h, то оно выводится, но потом зависание не заставляет себя ждать )). Насчет флажка я уже говорил, что пробовал это в 3-ем посте, но все равно не пашет. Насчет нежелательного вызова прерываний внутри обработчика - понимаю, и даже сам, когда начинал писать эту хрень по нескольку раз обдумывал это действие (давно пробовал программить под Dos, потом стал писать под Винду), но с другой стороны, а что если надо будет сделать в обработчике что-нибудь более серьезное, когда без прерываний не обойтись? И вообще, ведь любой обработчик - это обычная функция, которую я вызываю по всем правилам. Не понимаю, где здесь загвоздка - кто может, объясните, плиз.
сделай простейшую синхронизацию, вызывать int 21h из обработчика IRQ -- это моветон. Например, раздели код на "safe"- и "unsafe"-части (как красиво пишут в книжках). Unsafe -- как у тебя в обработчике int 9, т.е. дос потенциально может быть в нереентрантном состоянии. Safe -- места (точнее моменты), где ДОС можно вызывать. int9 получает управление, проверяет клавиши да флаги, если да -- маякует "safe"-части (если InDOS=1), мол, работай, ниггер -- выставляет флажок, который проверяется в 'безопасных' местах -- например, собственно в перехваченном int 21h или при обнаружении InDOS=0 в перехваченном int8. вдогонку: Код (Text): INT 21 34-- - DOS 2+ - GET ADDRESS OF INDOS FLAG Category: D - DOS kernel Inp.: AH = 34h Return: ES:BX -> one-byte InDOS flag Notes: this function executes on the DOS stack, and thus cannot be called while another DOS function is already executing; you should use this function once at the beginning of the program and store the returned pointer rather than calling it when requiring DOS access the value of InDOS is incremented whenever an INT 21 function begins and decremented whenever one completes during an INT 28 call, it is safe to call some INT 21 functions even though InDOS may be 01h instead of zero InDOS alone is not sufficient for determining when it is safe to enter DOS, as the critical error handling decrements InDOS and increments the critical error flag for the duration of the critical error. Thus, it is possible for InDOS to be zero even if DOS is busy. SMARTDRV 4.0 sets the InDOS flag while flushing its buffers to disk, then zeros it on completion the critical error flag is the byte immediately following InDOS in DOS 2.x, and the byte BEFORE the InDOS flag in DOS 3.0+ and DR DOS 3.41+ (except COMPAQ DOS 3.0, where the critical error flag is located 1AAh bytes BEFORE the critical section flag) for DOS 3.1+, an undocumented call exists to get the address of the critical error flag (see AX=5D06h) this function was undocumented prior to the release of DOS 5.0. SeeAlso: AX=5D06h,AX=5D0Bh,INT 15/AX=DE1Fh,INT 28 INT 21
_BC_ Собственно так и сделано в приведенном мною обработчике. Флаги выставляются в "безопасной" области и проверяются в главном цикле программы.