Во время разработки небольшого ядра я столкнулся со странной проблемой при загрузке процессоров приложений с использованием APIC.
Как указано в OSDev и Intel-Manual, процессор сначала переходит в реальный режим, и моя цель — заставить его работать в защищенном режиме. После настройки небольшого стека и включения строки «A20» и перехода к моему 32-битному коду я попытался очистить eax
, используя xor eax, eax
для здравомыслия.
К моему удивлению, было очищено только младшее слово eax
, но старшее слово осталось неизменным.
Забавно, но если я просто выполню xor ax, ax
вместо xor eax, eax
, регистр будет полностью очищен.
Ниже приведен мой код для начальной загрузки процессора приложения с помощью APIC:
; Extern reference to the GDTR
section .data
extern g_gdtr
; Serves as a temporary stack used for flushing the cpu-pipeline
SMP_BOOT_STACK_SIZE equ 64
smp_boot_stack:
dq 0
dq 0
dq 0
dq 0
section .text
global __smp_ap_rm_entry
align 0x1000
[bits 16]
; Real-Mode Entry point for other processor cores (AP's)
; after a INIT-SIPI-SIPI was issued
__smp_ap_rm_entry:
cli
xor ax, ax
mov ds, ax
mov ss, ax
lea bp, [ds:smp_boot_stack + SMP_BOOT_STACK_SIZE - 1]
mov sp, bp
; Enable A20 line
sti
in al, 0x92
or al, 2
out 0x92, al
cli
lgdt [ds:g_gdtr]
; Enable Protected Mode
mov eax, cr0
or eax, 0x1
mov cr0, eax
; Far jump
push 0x8
push __smp_ap_pm_entry
retf
align 4
[bits 32]
__smp_ap_pm_entry:
mov ax, word 0x10
; Doing this two times is somehow necessary (wtf?)
mov es, ax
mov es, ax
mov ss, ax
mov fs, ax
mov gs, ax
mov ds, ax
xor eax, eax
int 3 ; To check for changed values in qemu
jmp $
Более того, я также пытался присвоить регистру 32-битное значение, например mov eax, 0xDEADBEEF
, но остается только часть BEEF
.
Кто-нибудь знает, почему это не работает?
Дважды проверьте, что ваш
bits 32
действителен и машинный код правильный.xor ax, ax
работает вместоxor eax, eax
обычно означает, что ваш ассемблер выдал код для 16 бит.Если вы работаете в 32-битном режиме, почему дескриптор CS отображается как
CS64
?@ sj95126 Я не думаю, что правильно понял ваш ответ. Где вы с этим столкнулись?
В опубликованном вами выходном изображении QEMU строка, начинающаяся с
CS =0008
. 32-битный сегмент кода должен отображаться какCS32
, а не какCS64
. Вы уверены, что ваш GDT правильный?@ sj95126 Большое спасибо за подсказку, это действительно была проблема все это время!