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

I am reading this book: C, Assembly, and Program Execution on Intel® 64 Architecture (Igor Zhirkov).There is listing in chapter about global descriptot table:

书中的片段,不是真正的引导程序

清单3-1。启用保护模式loader_start32.asm

section .text
global start32
start32:
    lgdt cs:[_gdtr]
    mov eax, cr0 ;privileged instruction
    or al, 1 ;bit resposnible for protected mode
    mov cr0, eax
    jmp (0x1 << 3):start32 ;assign first seg selector to cs
    align 16
_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 
    align 16
 _gdt: 
    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)

我对此片段有几个疑问:

  1. I know cr0 - control register is not accessible without privileged, but then, how do I gain them from code in my case (after lgdt cs:[_gdtr])? In Intel doc, the lgdt instruction says:
将源操作数中的值加载到全局描述符表寄存器(GDTR)或中断描述符中   表寄存器(ID​​TR)

But ther is NO mention about gaining any privileges, so I should be not able to use cr0 in mov instruction. Therefor, when compiling getting first error: invalid combination of opcode and operands (in the row of mov eax, cr0 ;privileged instruction)

  1. Why did author used align 16? As far as I know, align X should be used in order to make custom memory boundary. So in this case, data should be align 16 bytes long. But, If I looked at the code, I see:

        _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 
    

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

  1. Moreover, the definition of label _gdt is:

    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)
    

That is 2 times double-word (8 bytes) + 8 times byte + 8 times byte. Altogether, the amount is 32 bytes, not 8 (as should be quadword in dq _gdt ; quadword).

The last question is also about align X

  1. How long will the instruction align X last? in the snippet, it is used twice and in both cases BEFORE label. So does it last only for particular frame of address (label)? If so, then how it will "know" when the address (label) ends? And after that, it will be default alignment again?

[Additional info for errors]: Compiled with this flag: nasm -felf32 somefile.nasm

I may added some other flags, to resolve the align error for 64-bit unsigned relocation zero-extended from 32 bits [-w+zext-reloc]. `

评论