Ошибка при подмене обработчика прерывания

Тема в разделе "WASM.ASSEMBLER", создана пользователем ManWithNoName, 4 сен 2005.

  1. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Надо для одной любительской оськи (работает в реалмоде x86) написать собственные обработчики прерываний, ну и вот стал я писать такую штуку(перопределяю обработчик прерывания от клавиатуры):



    oldintaddr = SetIntVect(0x09, Interrupt);



    unsigned long SetIntVect(int no, void(*foo)(void)) - устанавливает новый обработчик прерывания. Ну это работает. Обработчик устанавливается, но потом, после выполнения своих дел он должен вызвать исходный обработчик, поэтому я поступаю так:



    void Interrupt()

    {

    asm("addl $8, %esp");

    asm("popl %ebp"); // это всё издержки написания на си и ещё так коряво как я :)



    PutChar(".");



    asm("movl _oldintaddr, %eax");

    asm("pushl %eax");

    asm("retf");

    }



    Тогда код нового обработчика получается такой:



    _Interrupt:

    push long ebp

    mov long ebp, esp

    sub long esp, 8

    add long esp, 8

    pop long ebp

    sub long esp, 12

    push long LC8

    call _PutString

    add long esp, 16

    mov long eax, [_oldintaddr]

    push long eax

    retf

    mov esp, ebp

    pop ebp

    ret



    Убрав лишние команды, посути имеем, что мой обработчик делает:



    _Interrupt:

    sub long esp, 12

    push long LC8

    call _PutString

    add long esp, 16 ;вывод строки



    mov long eax, [_oldintaddr]

    push long eax

    retf



    В итоге, при нажатии на клавишу, действительно запускается мой обработчик, но на экране появляется не одно сообщение от PutString, а где то штук сто :) и всё... зависание. Правда VMWare работает, 100% грузит процессор. То есть там как то с возвратом из прерывания не так что то. Но я не пойму что.

    Конечно, это я скорее буду писать не на си, а на асме сразу, просто поначалу не стал заморачиваться... На сколько мне известно, при вызове прерывания сохраняются cs, ip и флаги - как это в стеке сохраняется, в каком порядке? И что я делаю не так? Рад любым подсказкам и советам.
     
  2. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Ой, тут я когда писал, опечатался в Interrupt. Там должно быть asm("movl [_oldintaddr], %eax"), а не asm("movl _oldintaddr, %eax");

    Но это ни чего не меняет. Эффект тот же :dntknw: Я не пойму в чём дело.
     
  3. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    И вот ещё: в переменной unsigned long oldintaddr - лежит, распечатывал, именно старый адрес обработчика, но, когда в Interrupt делаю такую вещь:

    asm("movl [_oldintaddr], %eax");

    asm("pushl %eax");



    asm("movl $0x78563412, %eax");

    asm("pushl %eax");



    asm("call _Halt");



    И смотрю стэк: 12 34 56 78-00 00 00 00-E2 22 6C EC-02 02 00 00-35 20 08 20-72 FF 20 00....... То есть почему то лежит 0? Или я чего то не понимаю.
     
  4. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    И вот ещё: в переменной unsigned long oldintaddr - лежит, распечатывал, именно старый адрес обработчика, но, когда в Interrupt делаю такую вещь:

    asm("movl [_oldintaddr], %eax");

    asm("pushl %eax");



    asm("movl $0x78563412, %eax");

    asm("pushl %eax");



    asm("call _Halt");



    И смотрю стэк: 12 34 56 78-00 00 00 00-E2 22 6C EC-02 02 00 00-35 20 08 20-72 FF 20 00....... То есть почему то лежит 0? Или я чего то не понимаю.
     
  5. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Я уже ближе к разгадке, но всё равно не понятно...

    Делаю там сразу, без _oldintaddr:



    asm("movl $0xF000E987, %eax");

    asm("pushl %eax");

    asm("retf");



    Имею при нажатии на кнопки например qwerty на экране:

    .q..w..e..r..t..y. - Почему окаймление с двух сторон, если PutString("."); Должен давать .q.w.e.r.t.y - и ещё с флагами, они у меня точно сохраняются, как это проще проверить? (И всё таки надо туда _oldintaddr писать, а не в ручную. Помогите советом)
     
  6. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    я в сях не силен, но опираясь на память и школьные паскалевские годы, вроде бы сначала надо получить вектор

    вызвав oldintaddr=GetIntVect(...), и только потом ставить SetIntVect



    А сдвух сторон, потому что прерывание срабатывает при нажатии и отпускании батона
     
  7. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Если бы это был Дос, то тогда да... а то это соовсем левая ось. За то, что "А сдвух сторон, потому что прерывание срабатывает при нажатии и отпускании батона" - большое спасибо. Остаётся единственный вопрос, почему у меня в eax не запихивается старый адрес - это постом выше. То есть я почти разобрался. А как отличить нажатие и отпускание кнопки, там какой нить сканкод хитрый посылается?
     
  8. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Тут, понимаешь GetIntVect - некорректное название - он же и устаналивает новый адрес, он же и возвращает старый... Правда там надо будет коегде сделать cli/sti.... А то что то мне не нравится его устройство.
     
  9. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    если я только не путаю, ох как давно это было, то какой-то код отпускания или нажатия на 80h больше...



    и в отладцике посмотри переменная _oldintaddr вообще что нибудь содержит?
     
  10. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    ага, спасибо. Да, я после установки прерывания нового - пишу отладочную печать oldintaddr - вроде тот адрес храниться, который соответствует обработчику этого 9го прерывания. По крайней мере не 0 :)
     
  11. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    Это надо твой код смотреть смотреть, пока мое(да думаю и не только мое) мышение не настолько развито, что бы по 3-м строчкам кода увидеть всю картину в динамике... :)
     
  12. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Ну ладно, спасибо и за то, что сказал. Какой код ты бы хотел увидеть? Просто, вот тут

    _Interrupt:

    sub long esp, 12

    push long LC8

    call _PutString

    add long esp, 16 ;вывод строки



    mov long eax, [_oldintaddr]

    push long eax

    retf

    не передаётся в eax _oldintaddr, хотя должен. А в стеке ноль :dntknw: Это действительно не просто понять человеку, со стороны. Придётся мне уж самому разбираться, наверное.
     
  13. KiNDeR

    KiNDeR New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2003
    Сообщения:
    258
    Адрес:
    Russia
    а возврат из прерывания не по iret/iretd делается? или возврат по retf это особенность твоей оси?
     
  14. ManWithNoName

    ManWithNoName New Member

    Публикаций:
    0
    Регистрация:
    4 сен 2005
    Сообщения:
    31
    Адрес:
    Москва
    Ну, здесь сделав необходимые мне действия я передаю управление старому обработчику прерывания, а для этого надо дальний вызов - запихиваю в стек сегмент:смещение и retf. А iret будет делаться но уже этим старым обработчиком прерывания. Он то вернёт уже в программу управление, и восстановит флаги ( вроде должен восстановить). Вот если бы я вообще не вызывал старый обработчик, то тогда бы мне пришлось делать iret.
     
  15. Chingachguk

    Chingachguk New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    340
    Ну для начала ты киляешь содержимое eax (ax) в своем обработчике - пиши сразу jmp dword ptr _old_hanler. Также проверь, что после push eax в стек попадает CS:IP в нужном порядке (для retf).