Как использовать контрольный регистр в более привилегированном режиме? - PullRequest
1 голос
/ 07 февраля 2020

Я читаю эту книгу: C, Сборка и выполнение программ на архитектуре Intel® 64 (Игорь Жирков) . В главе есть список о 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. Я знаю cr0 - регистр управления не доступен без привилегированных, но тогда как мне получить их из кода в моем случае (после lgdt cs:[_gdtr])? В Intel do c инструкция lgdt гласит:

Загружает значения исходного операнда в регистр таблицы глобальных дескрипторов (GDTR) или регистр таблицы дескрипторов прерываний (IDTR). )

Но нет никаких упоминаний о получении каких-либо привилегий, поэтому я не смогу использовать cr0 в mov инструкции. Поэтому при компиляции получается первая ошибка: неверная комбинация кода операции и операндов (в строке mov eax, cr0 ;privileged instruction)

Почему автор использовал align 16? Насколько я знаю, align X должен использоваться для того, чтобы создать пользовательскую границу памяти. Таким образом, в этом случае данные должны быть выровнены по 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 

Который, как указано в коде, имеет длину 10 байт , а не 16. компиляция, получая секунду ошибка: 64-битное перемещение без знака, расширенное нулями с 32 бит [-w + zext-reloc] .

Более того, определение метки _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)

То есть 2 раза двойное слово (8 байт) + 8 раз байт + 8 раз байт. В целом, это 32 байта, а не 8 (как и должно быть четырехугольное слово в dq _gdt ; quadword).

Последний вопрос также о align X

Как долго будет длиться инструкция align X? во фрагменте он используется дважды и в обоих случаях ДО метки. Так это продолжается только для определенного кадра адреса (метка)? Если так, то как он «узнает», когда адрес (метка) заканчивается? И после этого будет снова выравнивание по умолчанию?

[Дополнительная информация об ошибках]: Скомпилировано с этим флагом: nasm -felf32 somefile.nasm

Я могу добавить некоторые другие флаги, чтобы разрешить ошибка align для 64-bit unsigned relocation zero-extended from 32 bits [-w+zext-reloc]. `

...