тут просто попытка использовать многозадачность проблема в том, что на bochs-е все ОК, а на реальной машине идет перезагрузка Код (Text): format binary CODE_32_SEGMENT = 0x0050 CODE_32_SECTORS_COUNT = 4096 / 512 STACK_SIZE = 512 HEAD_STACK_ESP = 0x90000 + STACK_SIZE INTERRUPT_STACK_ESP = HEAD_STACK_ESP + STACK_SIZE org 7C00h use16 ; 16-bit code mov ax, 3 int 0x10 mov cl, 2 ; read from sector with number 2 xor ch, ch xor dh, dh mov ax, CODE_32_SEGMENT mov es, ax xor bx, bx mov ax, 0x0200 OR CODE_32_SECTORS_COUNT int 13h jmp CODE_32_SEGMENT:0000h align 512 org CODE_32_SEGMENT SHL 4 use16 xor ax, ax mov ds, ax db 0x66 lgdt [gdtr] cli in al, 0x70 or al, 0x80 out 0x70, al in al, 0x92 or al, 2 out 0x92, al mov eax, cr0 or al, 1 mov cr0, eax db 0x66 db 0xEA dd startup_32 dw 1 SHL 3 use32 startup_32: mov eax, 2 SHL 3 mov ds, ax mov ss, ax xor eax, eax mov es, ax mov esp, HEAD_STACK_ESP mov eax, 4 SHL 3 ltr ax mov ecx, 10 @@: call 3 SHL 3:0000h dec ecx jnz @B hlt @@: iretd handler_beginning: mov dword [ebx], eax add ebx, 2 inc eax jmp @B gdtr: dw BOOT_GDT_TABLE - 1 dd gdt gdt: dq 0x0000000000000000 dq 0x00CF98000000FFFF ; 32-bit code dq 0x00CF92000000FFFF ; 32-bit data ; interrupt TSS descriptor macro __TSS_DESCRIPTOR__ address, flags { dw 0x0067 ; TSS limit dw address AND 0x0000FFFF db (address AND 0x00FF0000) SHR 16 db flags db 0 db (address AND 0xFF000000) SHR 24 } ; TSS descriptors __TSS_DESCRIPTOR__ task_tss, 0x89 __TSS_DESCRIPTOR__ head_tss, 0x89 ; LDT descriptor for task switching dq 0x000082000000FFFF BOOT_GDT_TABLE = $ - gdt task_tss: dd 0 ; previos TSS descriptor selector dd INTERRUPT_STACK_ESP ; ring0 ESP dd 2 SHL 3 dd 5 dup(0) ; ring1 ESP, ring2 ESP, ring1 selector, ring2 selector, cr3 dd handler_beginning dd 0 ; eflags dd 0x0F30 ; eax dd 2 dup(0) ; ecx, edx dd 0xB800 SHL 4 ; ebx dd INTERRUPT_STACK_ESP ; esp dd 4 dup(0) ; ebp, esi, edi, es dd 1 SHL 3 ; cs dd 2 dup(2 SHL 3) ; ss, ds dd 2 dup(0) ; fs, gs dd 5 SHL 3 ; LDT selector dd 0 head_tss: db 96 dup(0) dd 5 SHL 3 ; LDT selector dd 0
Тоже еще не смотрел внимательно, но автору топика посоветую с помощью 'jmp $' найти инструкцию, которая вызывает перезагрузку. Так будет проще найти ошибку. (Почему-то подозреваю, что это 'ltr')
проще обработку исключений добавить) перезагрузка процессора инициируется скорее всего по следующей причине: какая-то неправильная инструкция генерирует исключение, допустим, #GP (General Protection). Т.к. обработчика у этого исключения нету (сброшен бит Present в IDT у этого вектора), процессор генерирует исключение двойной ошибки #DF (Double Fault). Т.к. не находится обработчика и у этого исключения, продолжение работы невозможно (оно невозможно в любом случае при генерации Double Fault), процессор переходит в shutdown-режим. Чипсет обнаруживает, что процессор "отбросил коньки" и выставляет сигнал #RESET
нет перезагрузка идет тут Код (Text): @@: call 3 SHL 3:0000h ; идет первый вызов dec ecx ; а вот сюда возврата нет jnz @B hlt @@: iretd ; ошибка тут, потому как на dec ecx перехода нет handler_beginning: mov dword [ebx], eax ; нормально выводит 0 add ebx, 2 inc eax jmp @B ; переходит на iretd не знаю, почему дальше iretd дело не идет NT установлен, селектор-линк в TSS правильный, селекторы сегментных регистров тоже...
Код (Text): format binary CODE_32_SEGMENT = 0x0050 CODE_32_SECTORS_COUNT = 4096 / 512 STACK_SIZE = 512 HEAD_STACK_ESP = 0x90000 + STACK_SIZE INTERRUPT_STACK_ESP = HEAD_STACK_ESP + STACK_SIZE org 7C00h use16 ; 16-bit code mov ax, 3 int 0x10 mov cl, 2 ; read from sector with number 2 xor ch, ch xor dh, dh mov ax, CODE_32_SEGMENT mov es, ax xor bx, bx ; offset in segment mov ax, 0x0200 OR CODE_32_SECTORS_COUNT int 13h ; read sectors jmp CODE_32_SEGMENT:0000h align 512 ; end of first sector org CODE_32_SEGMENT SHL 4 use16 xor ax, ax mov ds, ax db 0x66 lgdt [gdtr] cli in al, 0x70 or al, 0x80 out 0x70, al in al, 0x92 or al, 2 out 0x92, al mov eax, cr0 or al, 1 mov cr0, eax db 0x66 db 0xEA dd startup_32 dw 1 SHL 3 use32 startup_32: mov eax, 2 SHL 3 mov ds, ax mov ss, ax xor eax, eax mov es, ax mov esp, HEAD_STACK_ESP ; set stack mov eax, 4 SHL 3 ; head TSS descriptor selector ltr ax lidt [idtr] mov ecx, 10 @@: call 3 SHL 3:0000h dec ecx jnz @B hlt print: mov ebx, 0xB8000 mov ecx, 32 @@: mov edx, 0x0F30 shl eax, 1 adc edx, 0 mov dword [ebx], edx add ebx, 2 dec ecx jnz @B ret exception: repeat 0x20 mov eax, % - 1 call print hlt align 16 end repeat @@: iretd handler_beginning: mov dword [ebx], eax add ebx, 2 inc eax jmp @B gdtr: dw BOOT_GDT_TABLE - 1 dd gdt gdt: dq 0x0000000000000000 dq 0x00CF98000000FFFF ; 32-bit code dq 0x00CF92000000FFFF ; 32-bit data ; interrupt TSS descriptor macro __TSS_DESCRIPTOR__ address, flags { dw 0x0067 ; TSS limit dw address AND 0x0000FFFF db (address AND 0x00FF0000) SHR 16 db flags db 0 db (address AND 0xFF000000) SHR 24 } ; TSS descriptors __TSS_DESCRIPTOR__ interrupt_tss, 0x89 __TSS_DESCRIPTOR__ head_tss, 0x89 ; LDT descriptor for task switching dq 0x000082000000FFFF BOOT_GDT_TABLE = $ - gdt idtr: dw BOOT_IDT_TABLE - 1 dd idt idt: repeat 0x20 dw (exception + ((% - 1) SHL 4)) AND 0x0000FFFF dw 1 SHL 3 db 0 db 0x8E dw ((exception + ((% - 1) SHL 4)) AND 0xFFFF0000) SHR 16 end repeat BOOT_IDT_TABLE = $ - idt interrupt_tss: dd 0 ; previos TSS descriptor selector dd INTERRUPT_STACK_ESP ; ring0 ESP dd 2 SHL 3 dd 5 dup(0) ; ring1 ESP, ring2 ESP, ring1 selector, ring2 selector, cr3 dd handler_beginning dd 0 ; eflags (changed from code) dd 0x0F30 ; eax dd 2 dup(0) ; ecx, edx dd 0xB800 SHL 4 ; ebx dd INTERRUPT_STACK_ESP ; esp dd 4 dup(0) ; ebp, esi, edi, es dd 1 SHL 3 ; cs dd 2 dup(2 SHL 3) ; ss, ds dd 2 dup(0) ; fs, gs dd 5 SHL 3 ; LDT selector dd 0 head_tss: db 96 dup(0) ; first filled when APIC generate interrupt dd 5 SHL 3 ; LDT selector dd 0 исключение #TS
Прерывание 0Ah - Исключение недопустимого TSS (#TS - Invalid TSS Exception) посмотри на код ошибки в стеке какой у тебя.. там селектор tss должен быть
дело вот в чем Код (Text): mov ds, ax mov ss, ax xor eax, eax mov es, ax fs и gs на реальной машине и в VMWare оказывались в неопределенном состоянии в то время как в Bochs в них был загружен нулевой селектор, что и давало в итоге правильный результат на этом эмуляторе реальный код BIOS, вероятно для каких-то целей эти регистры использовал, тем самым делая их ненулевыми, а т. к у меня в коде они не обнуляются, в итоге при выполнении iretd из TSS (куда селекторы предварительно записывались) в fs и gs процессор пытался закэшировать дескрипторы, которых на самом деле в GDT не было, что и приводило к исключению