Беда с заменой обработчика системного таймера

Тема в разделе "WASM.ASSEMBLER", создана пользователем Arisu, 7 май 2008.

  1. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    Идея такова: в свободную (теоретически) память я закидываю свой обработчик, переустанавливаю вектор на него, а в конце своего обработчика возвращаюсь по старому вектору (что бы и досовский обработчик сделал свои дела).

    Но на деле по какой-то причине после того, как мой обработчик всё сделал - система виснет 8((. (сейчас запускаю это всё в DOS 6.22)

    Ниже небольшой код. (зы. на столе лежит две книги Юрова и одна Пирогова вроде сделал всё по науке)

    Код (Text):
    1. /* ----------------------------------------------------------------- */
    2. int main( void )
    3. {
    4.     void (*FuncPtr)( void ); //func ptr
    5.    
    6.     DWORD* Ptr;
    7.     DWORD  i;
    8.    
    9.         /* копируем мой обработчик куда-то */
    10.         FuncPtr = MyHandler;
    11.         Ptr = SYS_ADDR_TO_PTR( 0x000001E0 ); //якобы свободное место
    12.         memcpy( Ptr, FuncPtr, 32 );
    13.        
    14.         /* устанавливаем новый вектор */
    15.         Ptr = SYS_ADDR_TO_PTR( 0x0000020 ); //irq0
    16.         asm cli
    17.         *Ptr = SYS_PTR_TO_ADDR( 0x000001E0 );      
    18.         asm sti
    19.        
    20.         return 0;
    21. } /* --------------------------------------------------------------- */
    22.  
    23. /* ----------------------------------------------------------------- */
    24. void MyHandler( void )
    25. {
    26.        
    27. /* выводим на экран морду */
    28. asm {
    29.             xor bh, bh
    30.             mov dh, 1
    31.             mov dl, 1
    32.             mov ah, 2
    33.             int 0x10
    34.             mov al, 1
    35.             mov ah, 0x0A
    36.             mov cx, 1
    37.             int 0x10
    38.         }
    39.        
    40.         //SYSPC_MASTER_EOI;
    41.         //asm iret
    42.         /* возврат по старому вектору */
    43.         asm db 0xEA //jmp
    44.         asm dw 0x0000, 0x0020
    45. } /* --------------------------------------------------------------- */
     
  2. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    А чего бы ему не виснуть?
    Во-первых адрес 1E0 это никак не свободная память.
    Это часть таблицы векторов прерываний.
    Во-вторых переход к оригинальному обработчику написан неправильно.
    Это jmp 0020:0000
    А ты хотел наверное написать jmp 0:20h, но и это неправильно.
    По адресу 0:20h лежит указатель на оригинальный обработчик, ты управление передаёш в таблицу векторов прерываний (по сути на данные), а не на код обработчика.
    Надо примерно так:

    Код (Text):
    1. xor ax,ax
    2. mov ds,ax
    3. jmp dword ptr ds:[20h]
    Да и регистры изменённые сохранять в обработчике надо.
    В общем тут одна большая ошибка...
     
  3. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    cppasm

    1) цель: записать код именно в конец таблицы векторов прерываний и никуда иначе. Т.к. всё остальное беспощадно уничтожаеться загрузчиком одной ОС. А т.к. согласно карте таблици прерываний - всё, что после 1E0 это свободная или зарезервированная для басика память, то я ей и воспользовался

    2)с адресом джампа согласен я накосячил. но это произошло просто потому, что я криво прочитал содержимое ячейки по адресу 20. мне показалось что там было 20000, по которым я и прыгнул. И в это похоже как раз беда и заключаеться.. щас проверю.

    3) регистры сохранять пробовал. просто тут этого кода не привёл.

    ЗЫ
    кстати запись типа
    мой bASM отказываеться понимать.
     
  4. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Arisu
    Тогда значит убери квадратные скобки, либо поставь коды через db.
     
  5. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Попробуй тогда [ds:20h]
    А что ба bASM такой?
     
  6. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    я нашел где был сильно неправ ): сегмент нужно смещать на 4 влево. Я же в 16-и разрядном режиме.

    так вот.
    по адресу 20 лежит "0x0387001F". старшая часть это смещение, а младшая это сегмент. Соответственно я поменял джамп вот так:

    Код (Text):
    1. asm db 0xEA
    2. asm dw 0x0387, 0x01F0
    но легче почему-то не стало. система всё равно виснет.

    cppasm
    это борланд асемблер. который в bcc3.1 встроен.
     
  7. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
  8. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Arisu
    А надо asm dw 0x0387, 0x001F Сегмент надо смещать только при вычислении адреса, в командах процессор делает это автоматом.
     
  9. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    valterg
    да. и так тоже пробовал, но это не помогло к сожалению.

    я уже тихо начинаю рвать на себе волосы. всего-то надо подставить свой обработчик перед дефолтным и потом вернуть управление дефолтному 8(( а уже который день никак.
     
  10. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Я собственно так и подумал.
    Только у меня в нём компилируются оба варианта:
    Код (Text):
    1.   asm jmp dword ptr ds:[20h]
    2.   asm jmp dword ptr [ds:20h]
    Как конкретно ты считал это число? Как Dword читал?
    Если как Dword - ты его неправильно интерпретируеш.
    МЛАДШИЕ два байта (находятся по младшим адресам) это смещение, а СТАРШИЕ - сегмент.
     
  11. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    cppasm
    ты меня совсем запутал. "0x0387001F" это то, что выводиться в printf (код ниже)

    приведу ещё раз код. он немного изменился

    Код (Text):
    1. #define SYS_ADDR_TO_PTR( Addr )     \
    2.      (void*)( (((DWORD)Addr >> 4) << 16) | ((WORD)Addr & 0x0F) )
    3.        
    4. #define SYS_PTR_TO_ADDR( Ptr )      \
    5.      ( (((DWORD)Ptr & 0xFFFF0000) >> 12) + ((WORD)Ptr) )
    Код (Text):
    1. /* ----------------------------------------------------------------- */
    2. int main( void )
    3. {
    4.     void (*FuncPtr)( void ); //func ptr
    5.    
    6.     DWORD* VecPtr;
    7.     DWORD* MemPtr;
    8.    
    9.         VecPtr = SYS_ADDR_TO_PTR( 0x20 );
    10.         printf( "old vector = %08lX \n", *VecPtr );
    11.  
    12.         /* копируем мой обработчик куда-то */
    13.         FuncPtr = MyHandler;
    14.         MemPtr = SYS_ADDR_TO_PTR( 0x1E0 ); //якобы свободное место  
    15.         memcpy( MemPtr, FuncPtr, 64 );
    16.        
    17.         /* устанавливаем новый вектор */
    18.         asm cli    
    19.         *VecPtr = 0x1E0;
    20.         asm sti
    21.        
    22.         return 0;
    23. } /* --------------------------------------------------------------- */
    Код (Text):
    1. /* ----------------------------------------------------------------- */
    2. void MyHandler( void )
    3. {
    4.           asm pusha
    5.  
    6.         /* вывод рожи */
    7.  
    8.            asm {
    9.                xor bh, bh
    10.                mov dh, 1
    11.                mov dl, 1
    12.                mov ah, 2
    13.                int 0x10
    14.                mov al, 1
    15.                mov ah, 0x0A
    16.                mov cx, 1
    17.                int 0x10
    18.            }
    19.        
    20.           asm popa
    21.    
    22.         /* возврат по старому вектору */    
    23.         asm db 0xEA //jmp ofs,seg
    24.         asm dw 0x001F, 0x0387
    25. } /* --------------------------------------------------------------- */
    в итоге происходит прерывание и рожа таки выводиться. но дальше - висяк.

    пробовал в начале функции сохранять все регистры кроме флаговых (не использовать pusha), но это не спасает.
     
  12. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Arisu
    Тогда правильно asm dw 0х001F,0x0387 или просто dd 0x0387001F
     
  13. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    valterg
    пробовал и так.

    Вчера решил ещё забить на джамп и сделать просто обработчик который бы выводил рожу и всё.

    т.е. сделал С функцию с модификатором interrupt и в ней код вывода на экран. В теории всё должно было быть хорошо, однако и это приводит к зависону. 8(( что-то я делаю совсем не так видимо

    вспомнил, что я забыл про пролог функции, который вполне себе мешает, но попытавшись его компенсировать я ничего интересного не добился. Теперь ищу префикс к функции что бы она была сгенерирована без пролога

    короче мне это надоело. написал в виде шеллкода и всё стало нормально.