OSDev
http://osdev.su/

Как вернуть стек при выходе из софт прерывания.
http://osdev.su/viewtopic.php?f=6&t=1049
Страница 1 из 1

Автор:  iz56 [ 08 фев 2015, 10:17 ]
Заголовок сообщения:  Как вернуть стек при выходе из софт прерывания.

Застрял на такой проблеме - в обработчике софтварного прерывания нужно сделать выход из него с разрушенным стеком - вернуть на место sp -( real mode) Моя реализация- иногда работает - а потом нет.
Я сохраняю sp при старте обработчика - при выходе ресторю его и iret. Не покидает чувство что что-то не так.

Код:

;intman.asm
 
 
       macro    saveall
       {
 
       mov      dword [saveall32regs.eaxreg],eax

;mov      word [saveall16_seg_regs.gs_reg],sp
 
       mov      dword [saveall32regs.ebxreg],ebx
       mov      dword [saveall32regs.edxreg],edx
       mov      dword [saveall32regs.ecxreg],ecx
       mov      dword [saveall32regs.esireg],esi
       mov      dword [saveall32regs.edireg],edi
       pop      ax
       push     ax
       mov      word [saveall16_seg_regs.ds_reg],ax
       push     es
       pop      ax
       mov      word [saveall16_seg_regs.es_reg],ax
       push     fs
       pop      ax
       mov      word [saveall16_seg_regs.fs_reg],ax
       push     gs
       pop      ax
       mov      word [saveall16_seg_regs.gs_reg],ax
       }
 
new_handler:
       pushf
       pusha
       push     ds ;!saveall ds
       push     cs
       pop      ds
       saveall
       mov      dword eax,[saveall32regs.eaxreg]
       shl      ax,1 ;x2
       mov      bx,int_table ;> table.asm
       add      bx,ax
       jmp      word [bx]
 
int_exit: ;В случае ошибки - jmp here - как правильно вернуть стек на место?
;mov      word sp,[saveall16_seg_regs.sp_reg]
 
       pop      ds
       popa
       popf
       iret
 
 
saveall32regs:
.eaxreg dd 0
.ebxreg dd 0
.edxreg dd 0
.ecxreg dd 0
.esireg dd 0
.edireg dd 0
saveall16_seg_regs:
.ds_reg dw 0
.es_reg dw 0
.fs_reg dw 0
.gs_reg dw 0
.sp_reg dw 0
 
;EOF

Автор:  Nable [ 08 фев 2015, 14:23 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Фигня какая-то. Почему sp, а не esp? И почему такой изврат с сохранением ds (pop ax && push ax).
И зачем сохранять GPR в глобальную переменную, если после pusha (лучше, кстати, явно написать pushad) они и так есть на стеке?

Автор:  iz56 [ 08 фев 2015, 16:48 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Да я не сказал что use16 - 16bit cod in real mode. Потому sp вместо esp. Сегментный регестр DS сначала пушится - что бы потом его сохранить в адресном пространстве cамого обработчика прерывания - а для этого нужно установить свой ds который будет равным cs. Рабочий ,кстати, код. Единственная проблема - при ошибке - далеко внутри обработчика прерывания - происходит прямой jmp из многих и многих мест. Довольно глубоко в call-ах. Нужно правильно вернуться в вызвывшую программу. Я делал так - как закоментированно. Работает через раз. И еще не понятно следующее - в доках пишут что автоматом происходит блокирование прерываний при int 0х?? . Мне нужно видимо сразу делать sti?

Автор:  iz56 [ 08 фев 2015, 16:52 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Сохраняю все потому что там где нужны они будут - стек будет уже далеко.
Pusha не сохраняет 32бит регистры - только половинку.

Автор:  Nable [ 08 фев 2015, 17:22 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Дык pushad сохраняет 32-битные регистры. В 16-битном режиме это будет автоматом оттранслировано как префикс размера операнда (0x66, насколько помню) + pusha (в 32-битном режиме - просто как pusha). Флаги (в реальном режиме - только нижние 16 бит флагов), кстати, и так сохраняются/восстанавливаются при int/iret.
Ну и вообще не совсем ясно, зачем весь этот "crazy real-mode stuff". Использовать BIOS? Для этого есть x86emu, хотя лучше им (BIOS) вообще не пользоваться после начальной загрузки. Писать очередной DOS? Брр.

Да, кстати, а SS не модифицируется и стек не переполняется в процессе обработки прерывания?

Автор:  phantom-84 [ 08 фев 2015, 18:01 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Все правильно, прыгайте на int_exit. Только раскомментируйте "mov word sp,[saveall16_seg_regs.sp_reg]" возле этой метки. Зачем еще раз сохранять РОНы и так извращаться с сохранением сегментных регистров, тоже не понял (почему бы их не сохранять в стеке, как и все остальное).

Автор:  pavia [ 08 фев 2015, 18:11 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

При в вызове прерывания другие прерывания запрещаются. А по выходу включаются достигается это хранением регистра флагов в стеке.
popf
pushf - сохраняют не весь регистр, более того не все биты в нижней части.

DS - вы правильно сохраняете.
BP - забыли.

Стек может по портиться не только вверх но и вниз. Хотя вниз реже. Так что я бы всё сохранил в своём участке данных.

Автор:  Himik [ 08 фев 2015, 18:13 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Ещё команда cld может понадобиться, т.к. флаг направления строки бывает разный. И устанавливать на cs нужно не только ds, но и es, используемый многими инструкциями процессора. Обязательно использовать pushad, т.к. регистры 32-битные.
pavia, BP сохраняется через pusha.

Автор:  iz56 [ 08 фев 2015, 18:55 ]
Заголовок сообщения:  Re: Как вернуть стек при выходе из софт прерывания.

Спасибо , не ожидал - так четко и подробно все расписали.
Обычно не спрашиваю такого типа вопросы на форуме. Но здесь несколько дней в спешке делаю драйвер фат16 и устал уже искать все в интернете . Там у меня намешано так что самому нехорошо. Но это был такой эксперимент - решил написать полностью сам с нуля рабочий драйвер как можно быстрее. Где-то неделя ушла. Но теперь понимаю термин промышленное программирование в его тёмном смысле. Еще раз спасибо.
P.S. Пишу для ИС-ОС. У меня на аватарке (рядом снизу) ссылка на github wiki страницу.

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