Los pasos para crear el hilo virtual V86 son:
task_t taskV86; vm_address_t *addr; task_create(task_self(), FALSE, &taskV86); addr = (vm_address_t) 0x00; vm_allocate(taskV86, &addr, MEGABYTE, FALSE); vm_protect(taskV86, addr, MEGABYTE, FALSE, 0x07));
Note que el hilo que ejecuta el llamado task_create coloca a la tarea a la que pertenece como la tarea padre de la tarea V86. Al declarar FALSE el segundo argumento de este llamado, la tarea se crea sin memoria. Lo que permite que posteriormente se le asigne el área de memoria para mapear la memoria de la máquina DOS.
task_t taskV86; char *name; vm_address_t addr, dato, addr_i; int i; vm_allocate(task_self(), &dato, vm_page_size, TRUE); fd=open(name, O_RDONLY); addr_i = (char *) addr; while ( (n=read(fd, dato, vm_page_size)) > 0 ) { for (i=n+1; i<vm_page_size; i++) dato[i] = '\0'; vm_write(taskV86, addr_i, dato, vm_page_size); addr_i += vm_page_size; } vm_deallocate(task_self(), dato, vm_page_size);La lectura del código del programa 8086 se realiza desde el proceso monitor en un apágina de memoria y después se manda a escribir, por página, a la tarea V86.
typedef struct { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; unsigned int edi; unsigned int esi; unsigned int ebp; unsigned int esp; unsigned int ss; unsigned int eflags; unsigned int eip; unsigned int cs; unsigned int ds; unsigned int es; unsigned int fs; unsigned int gs; } i386_thread_state_t;Se puede observar que la estructura de datos contiene los distintos registros del procesador. Entonces, para crear un hilo V86, se debe crear un hilo Mach, y encender la bandera VM del registro eflags. Toda esta operación, se realiza con los llamados a Mach thread_create, para crear el hilo V86; thread_get_state, para obtener el estado inicial del hilo V86 (a través de una estructura i386_thread_state_t); y thread_set_state, para asignarle los valores necesarios para inicializar un hilo en modo virtual 8086. Como se muestra a continuación:
task_t taskV86; thread_t threadV86; port_t port_ex; i386_thread_state_t vm_thread_state; thread_create(taskV86, &threadV86); port_allocate(task_self(), &port_ex); thread_get_state(threadV86, i386_THREAD_STATE, (thread_state_t)(&vm_thread_state), &vm_state_count); vm_thread_state.eflags = (vm_thread_state.eflags | EFL_VM); vm_thread_state.eip = entry_point; vm_thread_state.cs = 0x00; vm_thread_state.ds = 0x60; vm_thread_state.ss = 0x00; vm_thread_state.gs = 0x00; vm_thread_state.es = 0x00; vm_thread_state.ebp = 0x00; vm_thread_state.eax = 0x00; vm_thread_state.ebx = 0x00; vm_thread_state.ecx = 0x00; vm_thread_state.edx = 0x00; vm_thread_state.edi = 0x00; vm_thread_state.esi = 0x00; vm_thread_state.esp = 0x60; thread_set_state(threadV86, i386_THREAD_STATE, (thread_state_t)(&vm_thread_state), vm_state_count);El llamado thread_get_state regresa la estructura del estado del hilo para poder inicializar los registros que se cargarán en el procesador. Una vez que se han obtenidos los valores del hilo, se enciende la bandera VM (Virtual Machine) del registro EFLAGS --para declarar que el hilo V86 efectivamente se ejecutará en modo virtual 8086-- y se le dan valores a los registros SS y SP para asignarle una pila, se le indica la dirección CS:IP del programa 8086 que se ejecutará. Y, finalmente, asignan estos valores al hilo V86.