Assembly 如何在更特权的模式下使用控制寄存器?

Assembly 如何在更特权的模式下使用控制寄存器?,assembly,x86-64,nasm,bootloader,osdev,Assembly,X86 64,Nasm,Bootloader,Osdev,我正在读这本书:。在关于全局描述符表的章节中列出了: 书中的片段,不是真正的引导程序 清单3-1。启用受保护模式加载程序\u start32.asm 如代码中所述,它的长度为10字节,而不是16字节。 因此,在编译时,会出现第二个错误: 64位无符号重定位零从32位[-w+zext reloc]扩展而来。 此外,标签的定义是: dd 0x00, 0x00 ; null descriptor db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 ;d

我正在读这本书:。在关于
全局描述符表的章节中列出了:

书中的片段,不是真正的引导程序 清单3-1。启用受保护模式加载程序\u start32.asm

如代码中所述,它的长度为10字节,而不是16字节。 因此,在编译时,会出现第二个错误: 64位无符号重定位零从32位[-w+zext reloc]扩展而来。

  • 此外,标签的定义是:

    dd 0x00, 0x00 ; null descriptor
    db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 ;differ by exec bit
    db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 ;execution off (0x92)
    
  • 即2倍双字(8字节)+8倍字节+8倍字节。总共是32字节,而不是8字节(在
    dq\u gdt;quadword
    中应该是四字)

    最后一个问题也是关于
    align X

  • 指令
    align X
    将持续多长时间? 在代码段中,它被使用了两次,在这两种情况下都是在添加标签之前使用。那么,它是否只适用于特定的地址框架(标签)?如果是这样,那么它如何“知道”地址(标签)何时结束?然后,它将再次成为默认对齐方式
  • [错误的其他信息]: 使用此标志编译:
    nasm-felf32 somefile.nasm

    我可能会添加一些其他标志,以解决从32位[-w+zext reloc]
    扩展而来的
    64位无符号重定位零的
    align
    错误。
    `

    Real模式没有特权/环级别,everything=内核模式。如果您正在编写16位引导加载程序,则可以执行特权指令,除非您进入保护模式并跳转到非特权代码段。听起来像是进入保护模式的引导加载程序,可以加载更多代码并在保护模式下跳转到它。很明显,它通过在CR0中设置该位来启用保护模式。如果假定它已经在16位或32位保护模式或64位模式下执行,则不需要这样做。我之所以提到64位模式,是因为dq是一个64位地址<代码>nasm-felf64
    对这一点很有意义。虽然地址是小尾数,但有价值的字节是前4个。要修复第一个错误,请将
    lgdt cs:[\u gdtr]
    更改为
    lgdt[cs:\u gdtr]
    。有关内存操作数的正确语法,请参阅NASM手册(错误消息指的是第4行,而不是您声称的第5行);指针部分指向表。这就是代码使用标签的原因。它们本身并不是一个描述符;它们是对描述符表的引用,指针+长度。如果没有GDT,就无法跳转到64位代码段。您确实需要64位模式的GDT。阅读有关x86如何工作的手册和/或osdev wiki:,并且,如果Real mode没有特权/环级别,则everything=内核模式。如果您正在编写16位引导加载程序,则可以执行特权指令,除非您进入保护模式并跳转到非特权代码段。听起来像是进入保护模式的引导加载程序,可以加载更多代码并在保护模式下跳转到它。很明显,它通过在CR0中设置该位来启用保护模式。如果假定它已经在16位或32位保护模式或64位模式下执行,则不需要这样做。我之所以提到64位模式,是因为dq是一个64位地址<代码>nasm-felf64对这一点很有意义。虽然地址是小尾数,但有价值的字节是前4个。要修复第一个错误,请将
    lgdt cs:[\u gdtr]
    更改为
    lgdt[cs:\u gdtr]
    。有关内存操作数的正确语法,请参阅NASM手册(错误消息指的是第4行,而不是您声称的第5行);指针部分指向表。这就是代码使用标签的原因。它们本身并不是一个描述符;它们是对描述符表的引用,指针+长度。如果没有GDT,就无法跳转到64位代码段。您确实需要64位模式的GDT。阅读有关x86如何工作的手册,和/或osdev wiki:,和
        _gdtr: ;stores GDT's last entry index + GDT address
        dw 47 ; word - 2 bytes
        dq _gdt ; quadword - 8 bytes ... then _gdtr should be 10 bytes long 
    
    dd 0x00, 0x00 ; null descriptor
    db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 ;differ by exec bit
    db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 ;execution off (0x92)