[英]I failed in switching the cpu from real-mode to protected-mode
我是根据Nick Blundell的书来做的。 我编写了一个MBR程序,该程序首先在实模式下运行,该程序中的某些指令会将CPU切换到保护模式。 首先,我将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
然后,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
指令jmp CODE_SEG:init_pm
将导致CPU崩溃并重新启动。 如果将其更改为jmp init_pm
,则以下指令mov ax,10
将导致CPU崩溃并重新启动。 书中说开关操作需要跳远。
您能帮我进行切换操作吗?
在您的gdt_descriptor
,您有限制和地址。 与大多数其他地址不同,这不是segment:offset地址。 它必须是一个线性地址。 作为MBR,您可能已将其从最初加载0x7C00的位置移走了。 gdt_descriptor
的地址(通常称为gdtr
)必须是您现在所在位置的线性地址。 您不确定要显示的代码不够多,但是我怀疑您的问题就在那里。
您的代码中存在几个问题:
gdt_code
描述符中缺少基数高位字的低字节。 只需在dw 0x0
之后添加db 0x0
dw 0x0
。 gdt_descriptor
必须包含线性地址。 是的,的确如此,但这并不是唯一需要线性地址的地方。 您可以在任何代码之前使用ORG
指令,也可以手动将原点添加到此字段。 lgdt
仍使用ds
寄存器进行seg:off
地址计算。 在org
下编写代码时,应将其设置为零。 0xFFFF
地址。 再次,检查代码的来源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.