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/ |