Я читаю эту книгу: 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)
У меня есть несколько вопросов к этому фрагменту:
- Я знаю
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]
. `