Setting a stack for a V86 task

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:process->kstack = (dword)&process->pl0_stacK+stack_size;
p = (dword)0x1fff8;
*--p = r->gs; /* gs */
*--p = r->fs; /* fs */
*--p = r->ds; /* ds */
*--p = r->es; /* es */
*--p = r->cs; /* ss */
*--p = 0xfff8; /* esp */
*--p = 0x20000L; /* eflags */
*--p = r->cs; /* cs */
*--p = r->eip; /* eip */
*--p = r->eax; /* eax */
*--p = r->ecx; /* ecx */
*--p = r->edx; /* edx */
*--p = r->ebx; /* ebx */
*--p = 0; /* nullesp*/
*--p = r->ebp; /* ebp */
*--p = r->esi; /* esi */
*--p = r->edi; /* edi */
*--p = 0x10; /* gs */
*--p = 0x10; /* fs */
*--p = 0x10; /* es */
*--p = 0x10; /* ds */
process->ustack = (dword)p;

_irq00:
pusha

push ds
push es
push fs
push gs

mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

push esp
mov eax, _TaskSwitch
call eax
add esp, 4

mov esp, eax

mov eax, cr0
or eax, 0x8 ; Set TS flag to use x87.fxsave with
mov cr0, eax ; device not available

pop gs
pop fs
pop es
pop ds

mov al, 0x20
out 0x20, al

popa
iret
sorry, but this code isn't very helpful for me. What are the values in the struct r?
And what is this code for?

Code: Select all

  mov eax, cr0
  or eax, 0x8  ; Set TS flag to use x87.fxsave with
  mov cr0, eax ; device not available
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

struct r is any kinda o struct you create, is all regs eax, ebx, esi...

this funcion you can call in that way:

memset(&r, 0, sizeof(regs));
r.eax = 0x03;
r.cs = r.ds = r.es = r.fs = r.gs = r.ss = 0x1000;
do_int86(0x10, &r, 0);

this is the struct r:

typedef struct regs {
dword gs, fs, es, ds; /* pushed the segs last */
dword edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */
dword int_no, err_code; /* our 'push byte #' and ecodes do thi */
dword eip;
word cs, csh;
dword eflags, useresp;
word ss, ss_h; /* pushed by the processor */
word v86_es, v86_esh;
word v86_ds, v86_dsh;
word v86_fs, v86_fsh;
word v86_gs, v86_gsh;
}regs;


and that:

mov eax, cr0
or eax, 0x8 ; Set TS flag to use x87.fxsave with
mov cr0, eax ; device not available

is to use fxsave, fxstor, " to use the math co-processor "

you can take that stuff off.
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

when I said " is to use math co-processor " I mean to use sse/sse2 mmx

struction in your multi-tasking os.

this a little code you just take a look, don´t need to use.

to create a vm86 task you cannot forget that vm86 task can use more

then 1MB of physical memory.

just from 0 to 0x100000
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:struct r is any kinda o struct you create, is all regs eax, ebx, esi...

this funcion you can call in that way:

memset(&r, 0, sizeof(regs));
r.eax = 0x03;
r.cs = r.ds = r.es = r.fs = r.gs = r.ss = 0x1000;
do_int86(0x10, &r, 0);

this is the struct r:

typedef struct regs {
dword gs, fs, es, ds; /* pushed the segs last */
dword edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */
dword int_no, err_code; /* our 'push byte #' and ecodes do thi */
dword eip;
word cs, csh;
dword eflags, useresp;
word ss, ss_h; /* pushed by the processor */
word v86_es, v86_esh;
word v86_ds, v86_dsh;
word v86_fs, v86_fsh;
word v86_gs, v86_gsh;
}regs;


and that:

mov eax, cr0
or eax, 0x8 ; Set TS flag to use x87.fxsave with
mov cr0, eax ; device not available

is to use fxsave, fxstor, " to use the math co-processor "

you can take that stuff off.
how must I fill the struct r?
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

his funcion you can call in that way:

regs r;

memset(&r, 0, sizeof(regs));
r.eax = 0x03;
r.cs = r.ds = r.es = r.fs = r.gs = r.ss = 0x1000;
do_int86(0x10, &r, 0);
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:his funcion you can call in that way:

regs r;

memset(&r, 0, sizeof(regs));
r.eax = 0x03;
r.cs = r.ds = r.es = r.fs = r.gs = r.ss = 0x1000;
do_int86(0x10, &r, 0);
I haven't the function do_int86...

I want to set a stack for a virtual 8086 mode task. It's different.
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

this is a vm86 stack

process->kstack = (dword)&process->pl0_stacK+stack_size;
p = (dword)0x1fff8;
*--p = r->gs; /* gs */
*--p = r->fs; /* fs */
*--p = r->ds; /* ds */
*--p = r->es; /* es */
*--p = r->cs; /* ss */
*--p = 0xfff8; /* esp */
*--p = 0x20000L; /* eflags */
*--p = r->cs; /* cs */
*--p = r->eip; /* eip */
*--p = r->eax; /* eax */
*--p = r->ecx; /* ecx */
*--p = r->edx; /* edx */
*--p = r->ebx; /* ebx */
*--p = 0; /* nullesp*/
*--p = r->ebp; /* ebp */
*--p = r->esi; /* esi */
*--p = r->edi; /* edi */
*--p = 0x10; /* gs */
*--p = 0x10; /* fs */
*--p = 0x10; /* es */
*--p = 0x10; /* ds */
process->ustack = (dword)p;
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:this is a vm86 stack

process->kstack = (dword)&process->pl0_stacK+stack_size;
p = (dword)0x1fff8;
*--p = r->gs; /* gs */
*--p = r->fs; /* fs */
*--p = r->ds; /* ds */
*--p = r->es; /* es */
*--p = r->cs; /* ss */
*--p = 0xfff8; /* esp */
*--p = 0x20000L; /* eflags */
*--p = r->cs; /* cs */
*--p = r->eip; /* eip */
*--p = r->eax; /* eax */
*--p = r->ecx; /* ecx */
*--p = r->edx; /* edx */
*--p = r->ebx; /* ebx */
*--p = 0; /* nullesp*/
*--p = r->ebp; /* ebp */
*--p = r->esi; /* esi */
*--p = r->edi; /* edi */
*--p = 0x10; /* gs */
*--p = 0x10; /* fs */
*--p = 0x10; /* es */
*--p = 0x10; /* ds */
process->ustack = (dword)p;
Where I take values of r???
I can't take these values from do_int86, because I don't have this function!!!
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

those values r->xxxx you put whatever you want
r->eflags should be 0x20000
r->eip 0

this is exception 0x13 in nasm

_isr13: ; GPF Handler
cli
push byte 13
jmp isr_common_stub

isr_common_stub:
pusha

push ds
push es
push fs
push gs

mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

push esp

mov eax, _fault_handler

call eax

add esp, 4

pop gs
pop fs
pop es
pop ds
popa

add esp, 8

iret


isr13 -> void fault_handler(regs *r)

inside on fault_handler

if ((r->eflags & 0x20000)) {
v86GPFHandler(r);
}
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:those values r->xxxx you put whatever you want
r->eflags should be 0x20000
r->eip 0

this is exception 0x13 in nasm

_isr13: ; GPF Handler
cli
push byte 13
jmp isr_common_stub

isr_common_stub:
pusha

push ds
push es
push fs
push gs

mov eax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

push esp

mov eax, _fault_handler

call eax

add esp, 4

pop gs
pop fs
pop es
pop ds
popa

add esp, 8

iret


isr13 -> void fault_handler(regs *r)

inside on fault_handler

if ((r->eflags & 0x20000)) {
v86GPFHandler(r);
}
ok. But I must know values for all regs in r
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

to create a vm86 task is so easy.

you just need to set up r->ds, r->es, r->fs, r->gs with segment you want,

example : r->ds = 0x1000;
that is the segment you load your vm86 code. I alway use that segment

and r-> cs = ds = es = fs = gs = 0x1000;

your r->eip = 0;

r->eflags = 0x20000;

your stack should be in the same segment

I´m using like that to setup a vm86 stack in my kernel

dword *p;

p = 0x1fff8;

and r->esp = 0xfff8;

you just need to setup that.

remember that vm86 task is the same of pm32 bits task except for the four " 4 " extra real mode segment register on top. in that order

p = (dword)0x1fff8;
*--p = r->gs; /* V86 gs */
*--p = r->fs; /* V86 fs */
*--p = r->ds; /* V86 ds */
*--p = r->es; /* V86 es */
*--p = r->cs; /* ss <= where should be 0x1000 too */
*--p = 0xfff8; /* esp <= where is the top of our vm86 stack */
*--p = 0x20000L; /* eflags */
*--p = r->cs; /* cs */
*--p = r->eip; /* eip */
*--p = r->eax; /* eax */
*--p = r->ecx; /* ecx */
*--p = r->edx; /* edx */
*--p = r->ebx; /* ebx */
*--p = 0; /* nullesp*/
*--p = r->ebp; /* ebp */
*--p = r->esi; /* esi */
*--p = r->edi; /* edi */
*--p = 0x10; /* PMODE gs */
*--p = 0x10; /* PMODE fs */
*--p = 0x10; /* PMODE es */
*--p = 0x10; /* PMODE ds */
I use that code below to setup a very simple program that just do a real mode INT and then later int 0x20 to close that program.
byte opcode[04];
opcode[0] = 0xCD;
opcode[1] = int_no;
opcode[2] = 0xCD;
opcode[3] = 0x20;
memset(0x10000, 0, 0xffff);
memcpy(0x10000, opcode, 0x04);

you see? I copy that code to segment 0x1000; 0x1000 * 0x10 = 0x10000;

just that
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:to create a vm86 task is so easy.

you just need to set up r->ds, r->es, r->fs, r->gs with segment you want,

example : r->ds = 0x1000;
that is the segment you load your vm86 code. I alway use that segment

and r-> cs = ds = es = fs = gs = 0x1000;

your r->eip = 0;

r->eflags = 0x20000;

your stack should be in the same segment

I´m using like that to setup a vm86 stack in my kernel

dword *p;

p = 0x1fff8;

and r->esp = 0xfff8;

you just need to setup that.

remember that vm86 task is the same of pm32 bits task except for the four " 4 " extra real mode segment register on top. in that order

p = (dword)0x1fff8;
*--p = r->gs; /* V86 gs */
*--p = r->fs; /* V86 fs */
*--p = r->ds; /* V86 ds */
*--p = r->es; /* V86 es */
*--p = r->cs; /* ss <= where should be 0x1000 too */
*--p = 0xfff8; /* esp <= where is the top of our vm86 stack */
*--p = 0x20000L; /* eflags */
*--p = r->cs; /* cs */
*--p = r->eip; /* eip */
*--p = r->eax; /* eax */
*--p = r->ecx; /* ecx */
*--p = r->edx; /* edx */
*--p = r->ebx; /* ebx */
*--p = 0; /* nullesp*/
*--p = r->ebp; /* ebp */
*--p = r->esi; /* esi */
*--p = r->edi; /* edi */
*--p = 0x10; /* PMODE gs */
*--p = 0x10; /* PMODE fs */
*--p = 0x10; /* PMODE es */
*--p = 0x10; /* PMODE ds */
I use that code below to setup a very simple program that just do a real mode INT and then later int 0x20 to close that program.
byte opcode[04];
opcode[0] = 0xCD;
opcode[1] = int_no;
opcode[2] = 0xCD;
opcode[3] = 0x20;
memset(0x10000, 0, 0xffff);
memcpy(0x10000, opcode, 0x04);

you see? I copy that code to segment 0x1000; 0x1000 * 0x10 = 0x10000;

just that
ok. Now I understand. But you are sure that r->cs must be the same as r-ds, r->es, r->fs and r->gs? And that r->eip must be 0?
Thank you!
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

sure, cuz in case yours needed being the same of my, we just need to setup like a common .com file. just one segment remember? 64kb.

and we load that program to that memory and setup the right segment values into segment registers.

for now, why we should put at r->eip " 0 ", cuz we´r not using program psp like msdos does, remember again org xxx?

so, we should use 0 <- for the first instruction. tell me if you´r getting some error. my msn is [email protected], do you have msn ?
let us have a talk. to make you understand better I can send to you my sources.[/b]
Post Reply