[英]I failed in switching the cpu from real-mode to protected-mode
I do this according a book by Nick Blundell. 我是根据Nick Blundell的书来做的。 I write a MBR program, which runs in real-mode firstly, and some instructions in the program will switch the cpu to protected-mode.
我编写了一个MBR程序,该程序首先在实模式下运行,该程序中的某些指令会将CPU切换到保护模式。 First I set the GDT like this:
首先,我将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
Then the cpu runs the following instructions: 然后,CPU运行以下指令:
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
The instruction jmp CODE_SEG:init_pm
will cause the cpu to crash and restart. 指令
jmp CODE_SEG:init_pm
将导致CPU崩溃并重新启动。 If I change this to jmp init_pm
, the following instruction mov ax,10
will cause the cpu to crash and restart. 如果将其更改为
jmp init_pm
,则以下指令mov ax,10
将导致CPU崩溃并重新启动。 And the book said the switching operation needs a long jump. 书中说开关操作需要跳远。
Could you please help me do the switching operation? 您能帮我进行切换操作吗?
In your gdt_descriptor
, you've got the limit and the address. 在您的
gdt_descriptor
,您有限制和地址。 Unlike most other addresses, this is NOT a segment:offset address. 与大多数其他地址不同,这不是segment:offset地址。 It needs to be a linear address.
它必须是一个线性地址。 As an MBR, you've probably moved it from where it was originally loaded at 0x7C00.
作为MBR,您可能已将其从最初加载0x7C00的位置移走了。 The address in your
gdt_descriptor
(often called gdtr
) needs to be the linear address of where you are now. gdt_descriptor
的地址(通常称为gdtr
)必须是您现在所在位置的线性地址。 You don't show quite enough code to be sure, but I suspect your problem is right in there. 您不确定要显示的代码不够多,但是我怀疑您的问题就在那里。
There are several problems in your code: 您的代码中存在几个问题:
gdt_code
descriptor. gdt_code
描述符中缺少基数高位字的低字节。 Simply add db 0x0
after dw 0x0
. dw 0x0
之后添加db 0x0
dw 0x0
。 gdt_descriptor
must contain linear address. gdt_descriptor
必须包含线性地址。 Yes, that's true, but it's not the only place where linear address is required. ORG
directive before any code, or manually add origin to this field. ORG
指令,也可以手动将原点添加到此字段。 lgdt
still uses ds
register for seg:off
address calculation. lgdt
仍使用ds
寄存器进行seg:off
地址计算。 You should have it set to zero when writing code under org
. org
下编写代码时,应将其设置为零。 0xFFFF
. 0xFFFF
地址。 Again, check origin of your code.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.