OSDev
http://osdev.su/

как правильно делать прерывания
http://osdev.su/viewtopic.php?f=6&t=737
Страница 1 из 2

Автор:  scuter [ 24 апр 2013, 15:55 ]
Заголовок сообщения:  как правильно делать прерывания

пробую сделать прерывания, и как то ничего не выходит с сегментными регистрами,

Код:
pushad ; сохраняю все регистры
mov cx , es
shl ecx, 16
mov cx , ss
mov bx , ds
shl ebx, 16
mov bx , fs
mov dx , gs
mov ax, 40h
mov ES, ax
mov SS, ax
mov DS, ax
mov FS, ax
mov GS, ax
mov esp, 500h
mov ebp, 500h
pushad

popad ; востанавливаю все регистры
mov gs , dx
mov fs , bx
shr ebx, 16
mov ds , bx
mov ss , cx
shr ecx, 16
mov es , cx
popad

возникает какой то глюк с сегментами,
програмный код встаёт и всё обламывается.

Автор:  Yoda [ 25 апр 2013, 10:38 ]
Заголовок сообщения:  Re: как правильно делать прерывания

Это код реального режима?
Зачем так извращаться с сегментными регистрами? Только ради использования команды POPAD? Нет никакого смысла. Лучше использовать непосредственно push/pop с сегментными регистрами, каждая такая команда использует ровно один байт. Будет занимать много меньше места и быстрей выполняться.
Этот код где находится? В обработчике прерывания?
Не забыл, что в конце обработчика необходимо использовать возврат инструкцией iret, а не ret?

Автор:  iz56 [ 25 апр 2013, 14:09 ]
Заголовок сообщения:  Re: как правильно делать прерывания

Вроде нельзя читать из сег. рег. в любой дроугой кроме AX.

Автор:  Yoda [ 25 апр 2013, 14:52 ]
Заголовок сообщения:  Re: как правильно делать прерывания

Можно в любой регистр кроме другого сегментного.

Автор:  SII [ 25 апр 2013, 15:51 ]
Заголовок сообщения:  Re: как правильно делать прерывания

А если б было нельзя, не прошла бы трансляция.

Автор:  scuter [ 26 апр 2013, 01:30 ]
Заголовок сообщения:  Re: как правильно делать прерывания

Yoda писал(а):
Это код реального режима?
Зачем так извращаться с сегментными регистрами? Только ради использования команды POPAD? Нет никакого смысла. Лучше использовать непосредственно push/pop с сегментными регистрами, каждая такая команда использует ровно один байт. Будет занимать много меньше места и быстрей выполняться.

просто команды push/pop то же используют сегментные регистры если бы у меня использовался только один кодовый сегмент и один сегмент данных проблем бы таких не было.
кстати
Код:
push ES
push SS
push DS
push FS
push GS

это я тоже использовал
Yoda писал(а):
Этот код где находится? В обработчике прерывания?
Не забыл, что в конце обработчика необходимо использовать возврат инструкцией iret, а не ret?

да в обработчике прерываний(Int32, Trap32) и в конце стоит iretd.




в IDT стоит Int32 Sel:Off=0008:0010171a и Trap32 Sel:Off=0008:0010171a
код ещё раз повторю
Код:
Interrupt_code:
pushad
mov cx , es
shl ecx, 16
mov cx , ss
mov bx , ds
shl ebx, 16
mov bx , fs
mov dx , gs
mov ax, 40h
mov ES, ax
mov SS, ax
mov DS, ax
mov FS, ax
mov GS, ax
mov esp, 500h
mov ebp, 500h
pushad
; код прерывания
popad
mov gs , dx
mov fs , bx
shr ebx, 16
mov ds , bx
mov ss , cx
shr ecx, 16
mov es , cx
popad
iret

Автор:  Yoda [ 26 апр 2013, 12:59 ]
Заголовок сообщения:  Re: как правильно делать прерывания

scuter писал(а):
просто команды push/pop то же используют сегментные регистры если бы у меня использовался только один кодовый сегмент и один сегмент данных проблем бы таких не было.

Таких проблем и нет. Достаточно сначала установить стек (сегмент и указатель) и push-ить/pop-ить остальные регистры/сегменты туда. Например, так:
Код:
   mov   [cs:SaveSS], ss
   mov   [cs:SaveSP], sp
   mov   ss, NewSS
   mov   sp, NewSP
   pushad
   push   ds
   push   es
   push   fs
   push   gs
   mov   ax, NewSeg
   mov   ds, ax
   mov   es, ax
   mov   fs, ax
   mov   gs, ax
   ...
   pop   gs
   pop   fs
   pop   es
   pop   ds
   popad
   iret


scuter писал(а):
в IDT стоит Int32 Sel:Off=0008:0010171a и Trap32 Sel:Off=0008:0010171a

Тэкс, я же не просто так спросил, работает ли обработчик в реальном режиме. Из приведённого заключаю, что нифига не в реальном, а в защищённом.
В защищённом режиме работа процессора (и прерываний) выглядит совершенно по-другому. Лучше всего взять тьюториал (например, этот) по работе прерываний в защищённом режиме. Причин, по которым у тебя всё может виснуть в защищённом режиме из-за некорректной работы обработчика прерываний - мильён и раскручивать/отлаживать код приходится очень мелкими изменениями.

Автор:  Himik [ 26 апр 2013, 13:41 ]
Заголовок сообщения:  Re: как правильно делать прерывания

Если в коде присутствует mov SS, ax, значит ты не настраивал TSS, или не разобрался с его работой. Загрузки SS в обработчике прерывания не должно быть.

Автор:  phantom-84 [ 26 апр 2013, 14:51 ]
Заголовок сообщения:  Re: как правильно делать прерывания

Да, обычно ss:esp настраивается автоматически или используется текущий стек. Я во вступительной части обработчиков настраиваю только ds и es, т.к. в режиме ядра при дальнейших вызовах вложенных подпрограмм эти регистры должны ссылаться на сегмент данных ядра. Примерно так:
Код:
  push ds
  push es

  push ss ; ds <- KDATA
  pop ds

  push ss ; es <- KDATA
  pop es
  ...
  pop es
  pop ds
  iret
Регистры fs и gs сохраняют/настраивают/восстанавливают вложенные подпрограммы, когда это необходимо.

В коде обработчика не увидел команды EOI.

Автор:  pavia [ 26 апр 2013, 15:09 ]
Заголовок сообщения:  Re: как правильно делать прерывания

В 0 кольце стек не перегружается, востальных перезагружается автоматом. Не перезагрузка вызывает трудности при переполнении стека или работе в сегметном режиме. Так что перезагружать или нет решать вам.
Лучше сделать как выше перезагрузить через кодовый сегмент.

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/