【问题标题】:I failed in switching the cpu from real-mode to protected-mode我无法将 cpu 从实模式切换到保护模式
【发布时间】:2013-09-02 08:29:15
【问题描述】:

我是根据 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崩溃并重启。而且书上说切换操作需要跳远。

你能帮我做一下切换操作吗?

【问题讨论】:

  • 我认为现代 CPU 可以让您利用 zif 指令来避免崩溃。
  • 先尝试reading OSDev,它涵盖了大部分基础知识。

标签: assembly protected-mode mbr real-mode gdt


【解决方案1】:

你的代码有几个问题:

  1. gdt_code 描述符中缺少 base 的高位字的低字节。只需在dw 0x0 之后添加db 0x0。
  2. Frank Kotler 写道,gdt_descriptor 必须包含线性地址。是的,确实如此,但它并不是唯一需要线性地址的地方。您可以在任何代码之前使用ORG 指令,或手动将来源添加到该字段。
  3. 指令lgdt 仍然使用ds 寄存器进行seg:off 地址计算。在org 下编写代码时应将其设置为零。
  4. 远跳转到保护模式也需要线性地址作为偏移量。请记住,此跳转是在兼容模式下执行的(因为它是在保护模式切换后执行的第一条指令)。它使用两个字节作为段选择器(在冒号之前),只使用两个字节作为偏移量(在冒号之后)。这意味着您不应该尝试跳转到高于0xFFFF 的地址。再次检查代码的来源。

【讨论】:

    【解决方案2】:

    在您的gdt_descriptor 中,您已经获得了限制和地址。与大多数其他地址不同,这不是段:偏移地址。它必须是线性地址。作为 MBR,您可能已将其从最初加载的 0x7C00 处移出。您的gdt_descriptor(通常称为gdtr)中的地址需要是您现在所在位置的线性地址。您没有显示足够的代码来确定,但我怀疑您的问题就在那里。

    【讨论】:

    • 还是谢谢大家^^
    猜你喜欢
    • 1970-01-01
    • 2016-01-18
    • 2012-06-16
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 2010-10-24
    • 1970-01-01
    相关资源
    最近更新 更多