Переход к CR0, который устанавливает или очищает PE, должен быть немедленно , за которым следует дальний прыжок для перезагрузки ПК, а затем необходимо перезагрузить %esp
, а также все регистры сегментов. Вам нужно сделать все это до того, как коснется стека или разрешит прерывания. И (как говорит drhirsch) невозможно вернуть из этой операции, даже если вы удалите адрес возврата перед тем, как лишить законной силы стек реального режима, поскольку адрес возврата является адресом реального режима.
Вы, похоже, пытаетесь использовать lret
для перезагрузки ПК и одновременного повторного включения прерываний, но это не сработает, поскольку указатель стека недействителен. Правильный код будет выглядеть примерно так:
switch_to_pmode:
# ... what you have ...
movl %eax, %cr0
.code32
ljmpl reload_segments
reload_segments:
# ... what you have ...
movl $pm_stack, %esp
sti # perhaps
# and then just go on with your startup code here
call foo
Вам следует прочитать руководство по системному программированию Intel , в частности главу 9 (инициализация машины), , особенно раздел 9.9, в котором подробно описывается, как выполнить переключение защищенного режима.