Простой загрузчик для входа в защищенный режим - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь написать простой загрузчик для архитектуры x86, который должен просто вывести символ «A», войти в защищенный режим, а затем остановиться.Мой код с комментариями выглядит следующим образом:

BITS 16
ORG 0x7c00

jmp 0:start ;set cs to 0

start:
mov ax,0x7c0
add ax,288
mov ss,ax
mov sp,4096

mov ax,0x7c0
mov ds,ax ;Sets segment descriptors for now

mov ah,0eh
mov al,65
int 10h ;Print A for test

jmp pretect ;Jump to a ~1 second delay before entering protected mode so we can see the 'A' if anything goes wrong

nod:
jmp nod ;Not used for now

gdtstp: ;global descriptor table
dq 0 ;Null
dw 0xffff ;Entry 08h, full 4gb
dw 0
db 0
db 0x9a
db 11001111b
db 0
dw 0xffff ;Entry 16h, full 4gb
dw 0
db 0
db 0x92
db 11001111b
db 0

gdtr: ;descriptor for gdt
dw 24
dd gdtstp

pretect: ;Wait for about 1 second before jumping to protect
mov esi,0x20000000
.loop:
dec esi
test esi, esi
jz protect
jmp .loop

protect: ;attempt to enter protected mode
cli
lgdt [gdtr] ;set gdt register
mov eax,cr0
or al,1
mov cr0,eax ;set bit 1 of cr0

jmp 08h:idle ;sets cs to 08h and jumps to idle

idle:
jmp idle ;Should stop here

times 510-($-$$) db 0
dw 0xaa55 ;magic number

Это в NASM и выполняется на qemu.У меня есть скользящее средство добавления задержки примерно в 1 секунду между выводом «А» и попыткой войти в защищенный режим.В настоящее время, когда я пытаюсь запустить этот код, он печатает «A», задерживается на секунду, затем перезагружается.Я не могу сказать, почему это так, но я предполагаю, что это вероятно потому, что глобальная таблица дескрипторов неверна или неправильно загружена, или потому что неправильный переход для установки селектора сегмента кода не верен.

Что должен делать мой коднужно сделать следующее: вывести «A», иметь GDT из 3 записей: нулевой дескриптор, сегмент кода всех 4 ГБ и сегмент данных всех 4 ГБ, иметь GDTR, который задает 24 байта и адрес GDT, подождите 1 секунду, отключите прерывания, загрузите GDT, включите защищенный режим, установите селектор сегмента кода с дальним переходом в режим ожидания, а затем оставайтесь там неопределенно долго.

Если есть возможность определить, что в моей сборкеКод не подходит для входа в защищенный режим, пожалуйста, укажите это.Я понимаю, что первоначальный загрузчик обычно не выполняет эту задачу, но я просто пытаюсь понять, как он работает с помощью минимально работающей программы.

РЕДАКТИРОВАТЬ: После изменения

mov ax,0x7c0
mov ds,ax

на

mov ax,0
mov ds,ax

и помещая mov ax,08h между idle: и jmp idle, qemu вылетает и выдает следующее:

qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a0000
EAX=feeb0010 EBX=00000000 ECX=00000000 EDX=ffffffff
ESI=00000000 EDI=8000007c EBP=00000000 ESP=00000ffc
EIP=0009fc6d EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =08e0 00008e00 0000ffff 00009300 DPL=0 DS16 [-WA]
DS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA]
FS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA]
GS =0000 00000000 0000ffff 00009300 DPL=0 DS16 [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00007c1f 00000018
IDT=     00000000 000003ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=feeb0010 CCD=feeb0010 CCO=ADDB
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000

1 Ответ

0 голосов
/ 04 октября 2018

Вам нужно загрузить ds с 0, а не с 7c0h.

В lgdt смещение в инструкции основано на 0.(Это единственная инструкция, которая использует DS.)

...