На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Название темы должно быть информативным !
Прежде чем задать вопрос, воспользуйтесь Поиском. и проверьте в FAQ (ЧАВО) Паскаля
Чтобы получить вразумительный ответ, подробно опишите проблему: что надо сделать, что не получается и номер ошибки (если есть), которую выводит компилятор.
Для вставки кода ваших программ используйте, пожалуйста, кнопку СODE=pas или выпадающий список СODE для других языков (подсветка синтаксиса).
[!] Как правильно задавать вопросы | Руководство по языку B.Pascal 7 & Objects/LR | Borland Pascal. Руководство пользователя
Модераторы: volvo877
  
> Обработка int 21h
    Подкажите, как правильно обрабатывать int_21h в паскале. Вот пример простенькой проги, где собственный обработчик прерывания просто вызывает стандартную процедуру его обработки. При запуске программа виснет.
    С прерываниями клавиатуры и таймера все работает, а вот 21 ... :(

    ExpandedWrap disabled
      {$M $800,0,0}   { 2K stack, no heap }
      uses Crt,Dos;
      var
        Int21Old: Procedure;
      {$F+}
      procedure NewInt21; interrupt;
      begin
        inline ($9C); { PUSHF -- Push flags }
        Int21Old;
      end;
      {$F-}
      begin
        GetIntVec($21,@Int21Old);
        SetIntVec($21,@NewInt21);
        Keep(0);
      end.
      Ты вызываешь Int21Old по CALL а надо по JMP,
      т.к. ты в стек уже засунул флаги. При возврате из int21 происходит неверный RET.
        Нет, JMP тут не поможет, всё равно повиснет, т.к. у тебя стоит директива interrupt (она в начале кода сохраняет в стеке регистры)!
        Лучше попробуй после Int21Old записать...
        ExpandedWrap disabled
          inline($9C/           { pushf }
                 $8F/$46/$16);  { pop word ptr [bp+16h] }

        Я не проверял, но работать должно!
        И ещё... если перед Int21Old в стек ничего не записывается, твой inline($9C) лучше делать в начале процедуры.
          Блин, слушай, я прогнал немного...
          Тут проблема не только в том, что флаги после Int21Old не сохраняются (для того, кто вызвал int 21h), а в том, что и регистры тоже не сохраняются! К тому же, оригинальному int 21h неверно передаются регистры ds и bp. Сделай тогда так...
          ExpandedWrap disabled
            {$S-}  { Это важно! }
            Procedure NewInt21;
            Begin
               Asm
                  push ds
                  push es
                  db 60h  { pusha }
                  mov ax,seg @Data
                  mov ds,ax
               End;
               { ...Твои процедуры... }
               Asm
                  mov ax,word ptr Int21Old[0]
                  mov word ptr cs:@ofs,ax
                  mov ax,word ptr Int21Old[2]
                  mov word ptr cs:@seg,ax
                  db 61h  { popa }
                  pop es
                  pop ds
                  pop bp  { нужно потому, что процедура делает "push bp" в самом начале }
                  db 0EAh { jmp ssss:oooo }
                @ofs: dw 0
                @seg: dw 0
               End
            End;

          И не забывай делать SwapVectors перед Keep!
          -------------------------------------------
          Кстати (это уже для FisherMan'а), pushf он делает потому, что iret вытаскивает 3 слова из стека (последний - как раз флаги), а retf (выход из процедуры) - всего 2, так что тут проблема не в этом...
            Облом!
            Сделал, как написал "7in"...
            Виснуть прога перестала, но процедура NewInt21 вызывается почему-то только 8 раз и все... Больше ей управление не передается :-(
              Пришли мне свою прогу на мыло eujin@mailru.com . Может, там другие глюки есть...
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0291 ]   [ 15 queries used ]   [ Generated: 18.04.24, 22:52 GMT ]