«вызов» после перехода в защищенный режим - PullRequest
5 голосов
/ 06 февраля 2012

Я пытаюсь перейти в защищенный режим в intel x86.

Я загрузил свой gdt с помощью lgdt, установил флаг P для cr0 на 1 и все селекторы сегментов, но когда я возвращаюсь из вызова функции, я не могу вызвать любую другую функцию или получаю эту ошибку

qemu: fatal: Trying to execute code outside RAM or ROM at 0xfeeb7c5b

Вот моя функция switch_to_pmode:

gdtr:
.short      23  // limit
gdtr_base:
.long       0   // base

switch_to_pmode:
    movl $null_segment, %eax        // Address of the first byte of the GDT
    movl %eax, gdtr_base

    cli             // disable interrupts

    lgdt (gdtr)

    movl %cr0, %eax
    or $0x1, %eax
    movl %eax, %cr0         // Set the PE flag

    push $0x8
    push $reload_segments
    lret

reload_segments:
    movl $0x10, %eax
    movl %eax, %ds
    movl %eax, %ss
    movl %eax, %es
    movl %eax, %fs
    movl %eax, %gs

    ret

foo:
    ret

И мои звонки

_start:
    call switch_to_pmode
    call foo // <----- Ouch!

Спасибо

Ответы [ 2 ]

3 голосов
/ 06 февраля 2012

Переход к 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, в котором подробно описывается, как выполнить переключение защищенного режима.

3 голосов
/ 06 февраля 2012

Вы должны убедиться, что ассемблер преобразует код, следующий за переключателем защищенного режима, в 32-битный код с директивой .code32 (или use32 in nasm).

Кроме того, ваш обратный адрес после подпрограммы защищенного режима больше не действителен. Вы не можете действительно вернуться к чему-либо после этого. Вместо этого установите esp на что-нибудь полезное и продолжайте.

...