2013-09-02 8 views
2

Я делаю это согласно книге Ника Бланделла. Я пишу программу MBR, которая сначала запускается в реальном режиме, а некоторые команды в программе будут переключать процессор в защищенный режим. Сначала я поставил GDT так:Мне не удалось переключить процессор из реального режима в защищенный режим

gdt_start: 

gdt_null: 
    dd 0x0 
    dd 0x0 

gdt_code: 
    dw 0xffff 
    dw 0x0 
    db 10011010b 
    db 11001111b 
    db 0x0 

gdt_data: 
    dw 0xffff 
    dw 0x0 
    db 0x0 
    db 10010010b 
    db 11001111b 
    db 0x0 

gdt_end: 

gdt_descriptor : 
    dw gdt_end - gdt_start - 1 
    dd gdt_start 
CODE_SEG equ gdt_code - gdt_start 
DATA_SEG equ gdt_data - gdt_start 

Затем процессор выполняет следующие инструкции:

cli 

    lgdt [gdt_descriptor] 
    mov eax,cr0 
    or eax,0x1 
    mov cr0,eax ;this will set the cpu to protected-mode   

;jmp $ ;I use this instrction to find where is wrong 
    jmp CODE_SEG:init_pm 

jmp $ 
[bits 32] 
init_pm: 
jmp $ 
    mov ax,10 
jmp $ 
    mov ds,eax 
    mov ss,eax 
jmp $ 
    mov es,ax 
    mov fs,ax 
    mov gs,ax 
    mov ebp,0x90000 
    mov esp,ebp 
    call BEGIN_PM 

Инструкция jmp CODE_SEG:init_pm заставит процессор сбой и перезагрузка. Если я изменю это на jmp init_pm, следующая инструкция mov ax,10 приведет к сбою процессора и его перезапуску. И в книге говорилось, что операция переключения требует длительного прыжка.

Не могли бы вы помочь мне выполнить операцию переключения?

+0

Я думаю, что современные процессоры позволяют использовать инструкцию 'zif', чтобы избежать дробления. –

+0

И попробуйте [чтение OSDev] (http://wiki.osdev.org/Protected_Mode) перед чем-либо еще, что охватывает большинство основ. –

ответ

0

Есть несколько проблем в вашем коде:

  1. Вы пропускаете младшие байты base's высокое слово в вашем gdt_code дескриптора. Просто добавьте db 0x0 после dw 0x0.
  2. Frank Kotler написал, что gdt_descriptor должен содержать линейный адрес. Да, это правда, но это не единственное место, где требуется линейный адрес. Вы можете использовать директиву ORG перед любым кодом или вручную добавить источник в это поле.
  3. Инструкция lgdt по-прежнему использует ds зарегистрироваться для seg:off расчет адреса. Вы должны установить его равным нулю при написании кода под org.
  4. Дальний переход в защищенный режим также требует линейного адреса, используемого в качестве смещения. Помните, что этот переход выполняется в режиме совместимости (так как это первая команда, выполняемая после переключателя защищенного режима). Он использует два байта для селектора сегментов (до двоеточия) и только два байта для смещения (после двоеточия). Это означает, что вы не должны пытаться перейти к адресу выше 0xFFFF. Снова проверьте исходный код.
0

В вашем gdt_descriptor у вас есть предел и адрес. В отличие от большинства других адресов, это НЕ - сегмент: адрес смещения. Он должен быть линейным адресом. Как MBR, вы, вероятно, переместили его с того места, где он был первоначально загружен в 0x7C00. Адрес в вашем gdt_descriptor (часто называемый gdtr) должен быть линейным адресом того, где вы сейчас находитесь. У вас недостаточно кода, чтобы быть уверенным, но я подозреваю, что ваша проблема прямо там.

+0

Спасибо всем тем ^^ – Akr