OSDev http://osdev.su/ |
|
Инициализация мультизадачности, или jmp far SEG:00 на GCC http://osdev.su/viewtopic.php?f=6&t=536 |
Страница 1 из 2 |
Автор: | DJ PhoeniX [ 02 май 2012, 04:07 ] |
Заголовок сообщения: | Инициализация мультизадачности, или jmp far SEG:00 на GCC |
Собственно, надо "далеко прыгнуть". Из подручных средств - gcc / gas, из данных - номер записи в GDT в переменной типа short. Котелок не варит, что очень жаль... |
Автор: | grindars [ 02 май 2012, 07:18 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
Сформируйте стек push-ами и сделайте дальний возврат (retf). Либо самомодификация. Примерно так: Код: static inline void longJump(unsigned int selector, unsigned int offset) __attribute__((noreturn)); static inline void longJump(unsigned int selector, unsigned int offset) { asm volatile("pushl %r\npushl %r\nlret"::"r"(selector), "r"(offset)); } Ах да, и если переход будет вызывать смену CPL, то надо еще добавить сохранение SS:ESP - retf их загружает в этом случае. |
Автор: | DJ PhoeniX [ 02 май 2012, 07:55 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
grindars писал(а): Либо самомодификация. По этому пути и пошёл в итоге: Код: short main_tss_d = create_task(0,0,0,0,0,0,0); asm("ltr %w0"::"a"(main_tss_d*8)); set_busy(main_tss_d,0); asm("mov %w0, _taskaddr"::"a"(main_tss_d*8)); asm(".byte 0xEA\n.word 0x0000\n_taskaddr:\n.word 0x0000"); set_busy(main_tss_d,1); printstr("Multitasking initiaized\n"); Только теперь я ловлю #GP на строчке Код: asm("ltr %w0"::"a"(main_tss_d*8)); Причём сам не знаю, почему и откуда. И это бесит. Вспомогательные процедуры: Код: typedef struct{
unsigned short limit_low, address_low; unsigned char address_3, access_rights, limit_hi_and_flags, address_4; } GD, *PGD; PGD gdt; void set_busy(short seg, char state){ if((state & 1) == 1) gdt[seg].access_rights |= 2; else gdt[seg].access_rights &= 0xFD; } void set_descriptor(unsigned short id, unsigned int limit, unsigned int address, unsigned char access_rights, unsigned char flags){ gdt[id].limit_low = limit & 0xFFFF; gdt[id].limit_hi_and_flags = ((limit >> 16) & 0xF) | ((flags & 0xF) << 4); gdt[id].address_low = address & 0xFFFF; gdt[id].address_3 = (address >> 16) & 0xFF; gdt[id].address_4 = (address >> 24) & 0xFF; gdt[id].access_rights = access_rights; } short create_task(int cr3, int eip, int eflags, int esp, short cs, short ss, short ds){ PTSS tss = malloc(sizeof(TSS)); short gdti = 6; // Just for debug set_descriptor(gdti,sizeof(TSS)-1,(unsigned int)tss,0x85,0); mfill(tss, sizeof(TSS), 0); tss->cr3 = cr3; tss->eip = eip; tss->eflags = eflags; tss->esp = esp; tss->cs = cs; tss->ss = ss; tss->ds = ds; return gdti; } |
Автор: | grindars [ 02 май 2012, 07:58 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
Код ошибки посмотрите, в мануале формат для #GP описан. |
Автор: | DJ PhoeniX [ 02 май 2012, 08:00 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
grindars писал(а): Код ошибки посмотрите, в мануале формат для #GP описан. В каком из мануалов, какой из кодов? ^_^ |
Автор: | grindars [ 02 май 2012, 08:06 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
Из контекста #GP вроде бы понятно - тот, что в стек процем при возникновении исключения помещается. Третий том мануала на IA-32. |
Автор: | DJ PhoeniX [ 02 май 2012, 08:13 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
Уже понял, только хз, как его вытащить из под нескольких CALL-ов, PUSH-ей и прочей фигни... |
Автор: | grindars [ 02 май 2012, 08:16 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
Вот как делаю я: Код: .type interrupt_common, @function .func interrupt_common interrupt_common: /* * CPU pushes: * ss * rsp * rflags * cs * rip * error code (if present) * Entry also pushes: * interrupt number */ pushq %rax pushq %rbx pushq %rcx pushq %rdx pushq %rbp pushq %rsi pushq %rdi pushq %r8 pushq %r9 pushq %r10 pushq %r11 pushq %r12 pushq %r13 pushq %r14 pushq %r15 // rdi - context pointer movq %rsp, %rdi callq InterruptDispatcher // if nonzero, pop error code testq %rax, %rax popq %r15 popq %r14 popq %r13 popq %r12 popq %r11 popq %r10 popq %r9 popq %r8 popq %rdi popq %rsi popq %rbp popq %rdx popq %rcx popq %rbx popq %rax jz 1f addq $8, %rsp 1: addq $8, %rsp iretq .endfunc .size interrupt_common, . - interrupt_common Соответственно, InterruptDispatcher первым аргументом получает контекст, где есть номер прерывания, код ошибки и все нужные регистры. |
Автор: | DJ PhoeniX [ 02 май 2012, 08:26 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
Ну, приблизительно высчитал, где оно может быть... Вероятно, 0x0030, что совпадает с селектором дескриптора... |
Автор: | DJ PhoeniX [ 03 май 2012, 05:43 ] |
Заголовок сообщения: | Re: Инициализация мультизадачности, или jmp far SEG:00 на GC |
А ошибка то всё ещё актуальна Побитово сравнил состояние памяти на момент вызова LTR (привет, варя и ида), ещё раз убедился, что всё идеально и должно работать, но... |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |