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)