I'm trying to setup a v8086 task (so that I can call int 10h) but all I can seem to get is an invalid opcode exception... I know my multitasking code works for 32bit pmode tasks, so I think the problem must be in how I setup the v8086 task...
In my init thread, I do this to call int 10h with 10c (132x60 text mode):
Code: Select all
struct regs *r = (struct regs *)mem.Calloc(sizeof(struct regs));
r->eax = 0x10c;
cpu.Interrupt(0x10, r);
mem.Free(r);
Code: Select all
void ia32CPU::Interrupt(int num, struct regs *r)
{
unsigned char *code = (unsigned char *)0x10000;
*code++ = 0xCD; // INT
*code++ = num;
*code++ = 0xCD; // INT
*code++ = 0x80; // 0x80 = Kill task
*code++ = 0xEB; // Infinite...
*code++ = 0xFE; // ...Loop
struct threadStruct *v8086thread = (struct threadStruct *)mem.Calloc(sizeof(struct threadStruct));
scheduler.CreateThread(scheduler._kernelProcess, v8086thread, 0x1000);
mem.Copy(&((ia32ThreadData *)v8086thread->archdata)->v8086regs, r, sizeof(struct threadStruct));
r->cs = r->ds = r->es = r->fs = r->gs = r->ss = 0x1000;
r->eip = 0;
tasks.InitThreadv86(v8086thread, r);
v8086thread->name = "V8086 Thread";
scheduler.AddSchedule(v8086thread);
while (v8086thread->state != TS_DEAD) ;
mem.Copy(r, &((ia32ThreadData *)v8086thread->archdata)->v8086regs, sizeof(struct threadStruct));
mem.Free(v8086thread);
}
Code: Select all
void ia32Tasks::InitThreadv86(struct threadStruct *thread, struct regs *r)
{
struct ia32ThreadData *adata = (struct ia32ThreadData *)mem.Calloc(sizeof(struct ia32ThreadData));
unsigned int *stack = (unsigned int *)0x1FFF8;
*--stack = r->gs;
*--stack = r->fs;
*--stack = r->ds;
*--stack = r->es;
*--stack = GDT_KDATA;
*--stack = r->eip;
*--stack = 0x20202; // EFLAGS
*--stack = r->ebp;
*--stack = 0xFFF8; // ESP
*--stack = r->edi;
*--stack = r->esi;
*--stack = r->edx;
*--stack = r->ecx;
*--stack = r->ebx;
*--stack = r->eax;
*--stack = 0x10;
*--stack = 0x10;
*--stack = 0x10;
*--stack = 0x10;
adata->stack = stack;
adata->esp = (unsigned int)stack;
adata->v8086 = false;
thread->archdata = (void *)adata;
}
Code: Select all
void ia32Tasks::Switch(struct threadStruct *old, struct threadStruct *thread)
{
if ((old != null) && (((struct ia32ThreadData*)old->archdata)->v8086))
return;
cpu.BeginAtomic();
//console.WriteLine("Switch from (%s::%s) to (%s::%s)",
// (old == null) ? "null" : old->proc->name,
// (old == null) ? "null" : old->name,
// thread->proc->name, thread->name);
struct ia32ThreadData *data = (struct ia32ThreadData *)thread->archdata;
oldesp = (old != null) ? &((struct ia32ThreadData*)old->archdata)->esp : null;
newesp = data->esp;
if (thread->proc->system)
{
if (data->v8086)
globalTSS.esp = 0x1000;
else
globalTSS.esp = null;
globalTSS.ss = null;
}
else
{
globalTSS.esp = newesp;
globalTSS.ss = GDT_UDATA;
}
cpu.EndAtomic();
//write_cr3((unsigned long)data->pageDirectory);
taskDoSwitch();
}
Code: Select all
extern oldesp, newesp
global taskDoSwitch
taskDoSwitch:
pushf ; Save registers
pusha
push ds
push es
push fs
push gs
mov eax, [oldesp] ; Check if oldesp is null
cmp eax, 0
je switch
mov [eax], esp ; Save old esp value
switch:
mov esp, [newesp] ; Switch to the new task
pop gs
pop fs
pop es
pop ds
popa ; Restore registers
popf
ret
Code: Select all
Fatal Error
An error has occured which the system cannot recover from. Please reboot the sys
tem and report any information shown below should the problem persist
Invalid Opcode Exception
GS 0x10 FS 0x10 ES 0x10 DS 0x10
EDI 0x10C ESI 0x0 EBP 0x0 ESP 0x1FFCC EBX 0x0 EDX 0x0 ECX 0xFFF8 EAX 0x0
INT 6h/6 ERR 0
EIP 0x3 CS 0x8 EFLAGS 0x10282 USRESP 0x0 SS 0x10