forked from KolibriOS/kolibrios
link dll
git-svn-id: svn://kolibrios.org@908 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
54e9661045
commit
9ad23608e6
@ -354,6 +354,11 @@ REG_ESI equ (RING0_STACK_SIZE-48)
|
|||||||
REG_EDI equ (RING0_STACK_SIZE-52)
|
REG_EDI equ (RING0_STACK_SIZE-52)
|
||||||
REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return
|
REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return
|
||||||
|
|
||||||
|
REG_USTACK equ (RING0_STACK_SIZE-56)
|
||||||
|
REG_CSTACK equ (RING0_STACK_SIZE-60)
|
||||||
|
REG_RAW equ (RING0_STACK_SIZE-64)
|
||||||
|
REG_RESTART equ (RING0_STACK_SIZE-68)
|
||||||
|
REG_ENTRY equ (RING0_STACK_SIZE-72)
|
||||||
|
|
||||||
PG_UNMAP equ 0x000
|
PG_UNMAP equ 0x000
|
||||||
PG_MAP equ 0x001
|
PG_MAP equ 0x001
|
||||||
|
@ -7,12 +7,55 @@
|
|||||||
#include <slab.h>
|
#include <slab.h>
|
||||||
#include <pe.h>
|
#include <pe.h>
|
||||||
|
|
||||||
|
#pragma pack(push,4)
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char app_name[16];
|
||||||
|
addr_t fpu_state; /* +16 */
|
||||||
|
count_t ev_count; /* +20 */
|
||||||
|
addr_t fpu_handler; /* +24 */
|
||||||
|
addr_t sse_handler; /* +28 */
|
||||||
|
addr_t pl0_stack; /* +32 */
|
||||||
|
|
||||||
|
addr_t heap_base; /* +36 */
|
||||||
|
addr_t heap_top; /* +40 */
|
||||||
|
addr_t cursor; /* +44 */
|
||||||
|
addr_t fd_ev; /* +48 */
|
||||||
|
addr_t bk_ev; /* +52 */
|
||||||
|
addr_t fd_obj; /* +56 */
|
||||||
|
addr_t bk_obj; /* +60 */
|
||||||
|
addr_t saved_esp; /* +64 */
|
||||||
|
addr_t io_map[2]; /* +68 */
|
||||||
|
|
||||||
|
u32_t dbg_state; /* +76 */
|
||||||
|
char *cur_dir; /* +80 */
|
||||||
|
count_t wait_timeout; /* +84 */
|
||||||
|
addr_t saved_esp0; /* +88 */
|
||||||
|
|
||||||
|
link_t dll_list; /* +92 */
|
||||||
|
|
||||||
|
u32_t reserved0[7]; /* +100 db 28 dup(?) */
|
||||||
|
|
||||||
|
addr_t wnd_shape; /* +128 */
|
||||||
|
u32_t wnd_shape_scale; /* +132 */
|
||||||
|
u32_t reserved1; /* +136 */
|
||||||
|
size_t mem_size; /* +140 */
|
||||||
|
}appdata_t;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
extern appdata_t *current_slot;
|
||||||
|
|
||||||
|
bool link_pe(addr_t img_base);
|
||||||
|
|
||||||
int __stdcall strncmp(const char *s1, const char *s2, size_t n);
|
int __stdcall strncmp(const char *s1, const char *s2, size_t n);
|
||||||
|
|
||||||
extern int __stdcall mnt_exec(void *raw, size_t raw_size, char *path,
|
extern int __stdcall mnt_exec(void *raw, size_t raw_size, char *path,
|
||||||
char *cmdline, u32_t flags) asm ("mnt_exec");
|
char *cmdline, u32_t flags) asm ("mnt_exec");
|
||||||
|
|
||||||
static dll_t core_dll;
|
dll_t core_dll;
|
||||||
|
|
||||||
|
slab_cache_t *dll_slab;
|
||||||
|
|
||||||
static char* strupr(char *str )
|
static char* strupr(char *str )
|
||||||
{
|
{
|
||||||
@ -84,6 +127,8 @@ void init_core_dll()
|
|||||||
nt->OptionalHeader.DataDirectory[0].VirtualAddress);
|
nt->OptionalHeader.DataDirectory[0].VirtualAddress);
|
||||||
core_dll.img_name = strupr(MakePtr(char*, LOAD_BASE, exp->Name));
|
core_dll.img_name = strupr(MakePtr(char*, LOAD_BASE, exp->Name));
|
||||||
|
|
||||||
|
dll_slab = slab_cache_create(sizeof(dll_t), 16,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
|
||||||
|
|
||||||
DBG("%s base %x size %x sections %d exports %x\n",
|
DBG("%s base %x size %x sections %d exports %x\n",
|
||||||
core_dll.img_name, core_dll.img_base,
|
core_dll.img_name, core_dll.img_base,
|
||||||
core_dll.img_size, nt->FileHeader.NumberOfSections,
|
core_dll.img_size, nt->FileHeader.NumberOfSections,
|
||||||
@ -91,9 +136,9 @@ void init_core_dll()
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
dll_t * find_dll(const char *name)
|
dll_t * find_dll(link_t *list, const char *name)
|
||||||
{
|
{
|
||||||
dll_t* dll = &core_dll;
|
dll_t* dll = (dll_t*)list;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -102,7 +147,7 @@ dll_t * find_dll(const char *name)
|
|||||||
|
|
||||||
dll = (dll_t*)dll->link.next;
|
dll = (dll_t*)dll->link.next;
|
||||||
|
|
||||||
}while(&dll->link != &core_dll.link);
|
}while(&dll->link != list);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
@ -183,15 +228,20 @@ typedef struct
|
|||||||
}exec_stack_t;
|
}exec_stack_t;
|
||||||
|
|
||||||
|
|
||||||
addr_t new_app_space(void);
|
addr_t __fastcall pe_app_space(size_t size);
|
||||||
|
|
||||||
int __stdcall pe_app_param(char *path, void *raw, addr_t ex_pg_dir,
|
int __stdcall pe_app_param(char *path, void *raw, addr_t ex_pg_dir,
|
||||||
addr_t ex_stack_page) asm ("pe_app_param");
|
exec_stack_t *ex_stack) asm ("pe_app_param");
|
||||||
|
|
||||||
int sys_exec(char *path, char *cmdline, u32_t flags)
|
int sys_exec(char *path, char *cmdline, u32_t flags)
|
||||||
{
|
{
|
||||||
|
PIMAGE_DOS_HEADER dos;
|
||||||
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
|
|
||||||
|
size_t img_size;
|
||||||
|
count_t img_pages;
|
||||||
|
count_t img_tabs;
|
||||||
addr_t ex_pg_dir;
|
addr_t ex_pg_dir;
|
||||||
addr_t ex_stack_tab;
|
|
||||||
addr_t ex_stack_page;
|
addr_t ex_stack_page;
|
||||||
addr_t ex_pl0_stack;
|
addr_t ex_pl0_stack;
|
||||||
|
|
||||||
@ -257,22 +307,23 @@ int sys_exec(char *path, char *cmdline, u32_t flags)
|
|||||||
return -30;
|
return -30;
|
||||||
}
|
}
|
||||||
|
|
||||||
ex_pg_dir = new_app_space();
|
ex_stack_page = core_alloc(0); /* 2^0 = 1 page */
|
||||||
|
if( ! ex_stack_page )
|
||||||
if( !ex_pg_dir )
|
|
||||||
{
|
{
|
||||||
mem_free(raw);
|
mem_free(raw);
|
||||||
return -30; /* FIXME */
|
return -30; /* FIXME */
|
||||||
};
|
};
|
||||||
|
|
||||||
ex_stack_tab = ex_pg_dir + 4096;
|
dos = (PIMAGE_DOS_HEADER)raw;
|
||||||
ex_pl0_stack = ex_pg_dir + 4096 * 2;
|
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||||
|
|
||||||
ex_stack_page = core_alloc(0); /* 2^0 = 1 page */
|
img_size = nt->OptionalHeader.SizeOfImage;
|
||||||
|
|
||||||
if( ! ex_stack_page )
|
ex_pg_dir = pe_app_space(img_size);
|
||||||
|
|
||||||
|
if( !ex_pg_dir )
|
||||||
{
|
{
|
||||||
core_free(ex_stack_tab);
|
core_free(ex_stack_page);
|
||||||
mem_free(raw);
|
mem_free(raw);
|
||||||
return -30; /* FIXME */
|
return -30; /* FIXME */
|
||||||
};
|
};
|
||||||
@ -284,8 +335,6 @@ int sys_exec(char *path, char *cmdline, u32_t flags)
|
|||||||
:"c"(1024),"D"(ex_stack_page + OS_BASE)
|
:"c"(1024),"D"(ex_stack_page + OS_BASE)
|
||||||
:"eax","cc");
|
:"eax","cc");
|
||||||
|
|
||||||
((u32_t*)(ex_stack_tab+OS_BASE))[1023] = ex_stack_page | 7;
|
|
||||||
|
|
||||||
ex_stack = (exec_stack_t*)(ex_stack_page + OS_BASE
|
ex_stack = (exec_stack_t*)(ex_stack_page + OS_BASE
|
||||||
+ PAGE_SIZE - stack_size);
|
+ PAGE_SIZE - stack_size);
|
||||||
ex_stack->argc = 2;
|
ex_stack->argc = 2;
|
||||||
@ -293,7 +342,7 @@ int sys_exec(char *path, char *cmdline, u32_t flags)
|
|||||||
ex_path = MakePtr(char*, ex_stack, sizeof(exec_stack_t)+AUX_COUNT*sizeof(auxv_t));
|
ex_path = MakePtr(char*, ex_stack, sizeof(exec_stack_t)+AUX_COUNT*sizeof(auxv_t));
|
||||||
|
|
||||||
memcpy(ex_path, path, pathsize);
|
memcpy(ex_path, path, pathsize);
|
||||||
ex_stack->path = (char*)(((addr_t)ex_path & 0xFFF) + 0x7FCFF000); /* top of stack */
|
ex_stack->path = (char*)(((addr_t)ex_path & 0xFFF) + 0x7FFFF000); /* top of stack */
|
||||||
|
|
||||||
if( cmdline )
|
if( cmdline )
|
||||||
{
|
{
|
||||||
@ -310,51 +359,56 @@ int sys_exec(char *path, char *cmdline, u32_t flags)
|
|||||||
DBG("create stack at %x\n\tpath %x\n\tcmdline %x\n",
|
DBG("create stack at %x\n\tpath %x\n\tcmdline %x\n",
|
||||||
ex_stack, ex_stack->path, ex_stack->cmdline);
|
ex_stack, ex_stack->path, ex_stack->cmdline);
|
||||||
|
|
||||||
pe_app_param(path, raw, ex_pg_dir, ex_stack_page);
|
pe_app_param(path, raw, ex_pg_dir, ex_stack);
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define master_tab (page_tabs+ (page_tabs>>10))
|
#define master_tab (page_tabs+ (page_tabs>>10))
|
||||||
|
|
||||||
void sys_app_entry(addr_t raw, addr_t ex_stack)
|
typedef struct
|
||||||
|
{
|
||||||
|
u32_t edi;
|
||||||
|
u32_t esi;
|
||||||
|
u32_t ebp;
|
||||||
|
u32_t esp;
|
||||||
|
u32_t ebx;
|
||||||
|
u32_t edx;
|
||||||
|
u32_t ecx;
|
||||||
|
u32_t eax;
|
||||||
|
u32_t eip;
|
||||||
|
u32_t cs;
|
||||||
|
u32_t eflags;
|
||||||
|
u32_t pe_sp;
|
||||||
|
u32_t pe_ss;
|
||||||
|
}thr_stack_t;
|
||||||
|
|
||||||
|
#define EFL_IF 0x0200
|
||||||
|
#define EFL_IOPL1 0x1000
|
||||||
|
#define EFL_IOPL2 0x2000
|
||||||
|
#define EFL_IOPL3 0x3000
|
||||||
|
|
||||||
|
void sys_app_entry(addr_t raw, thr_stack_t *thr_stack, exec_stack_t *ex_stack)
|
||||||
{
|
{
|
||||||
PIMAGE_DOS_HEADER dos;
|
PIMAGE_DOS_HEADER dos;
|
||||||
PIMAGE_NT_HEADERS32 nt;
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
|
|
||||||
size_t img_size;
|
size_t img_size;
|
||||||
count_t img_pages;
|
count_t img_pages;
|
||||||
count_t img_tabs;
|
|
||||||
count_t i;
|
count_t i;
|
||||||
u32_t tmp;
|
u32_t tmp;
|
||||||
|
|
||||||
__asm__ __volatile__ ("sti");
|
__asm__ __volatile__ ("sti");
|
||||||
|
|
||||||
DBG("pe_app_entry: raw %x esp %x\n", raw, ex_stack);
|
|
||||||
|
|
||||||
dos = (PIMAGE_DOS_HEADER)raw;
|
dos = (PIMAGE_DOS_HEADER)raw;
|
||||||
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||||
|
|
||||||
img_size = nt->OptionalHeader.SizeOfImage;
|
img_size = nt->OptionalHeader.SizeOfImage;
|
||||||
|
|
||||||
|
current_slot->mem_size = img_size;
|
||||||
|
|
||||||
|
list_initialize(¤t_slot->dll_list);
|
||||||
|
|
||||||
img_pages = img_size >> 12;
|
img_pages = img_size >> 12;
|
||||||
img_tabs = ((img_size + 0x3FFFFF) & ~0x3FFFFF) >> 22;
|
|
||||||
|
|
||||||
DBG("app pages %d app tabs %d\n", img_pages, img_tabs);
|
|
||||||
|
|
||||||
for(i = 0; i < img_tabs; i++)
|
|
||||||
{
|
|
||||||
addr_t tab = core_alloc(0);
|
|
||||||
((u32_t*)master_tab)[i] = tab|7; /* FIXME */
|
|
||||||
}
|
|
||||||
|
|
||||||
((u32_t*)master_tab)[0x7FC/4] = (ex_stack & 0xFFFFF000)|7; /* FIXME */
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"xorl %%eax, %%eax \n\t"
|
|
||||||
"rep stosl"
|
|
||||||
:"=c"(tmp),"=D"(tmp)
|
|
||||||
:"c"(img_tabs<<10),"D"(page_tabs)
|
|
||||||
:"eax","cc");
|
|
||||||
|
|
||||||
for(i = 0; i < img_pages; i++)
|
for(i = 0; i < img_pages; i++)
|
||||||
{
|
{
|
||||||
@ -362,17 +416,256 @@ void sys_app_entry(addr_t raw, addr_t ex_stack)
|
|||||||
((u32_t*)page_tabs)[i] = page | 7; /* FIXME */
|
((u32_t*)page_tabs)[i] = page | 7; /* FIXME */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr_t stack_page = ((addr_t)ex_stack-OS_BASE) & ~4095;
|
||||||
|
((u32_t*)page_tabs)[0x7FFFF000>>12] = stack_page | 7;
|
||||||
|
|
||||||
create_image(0, raw);
|
create_image(0, raw);
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
init_user_heap();
|
||||||
"xchgw %bx, %bx");
|
|
||||||
|
if (! link_pe(0))
|
||||||
|
{
|
||||||
|
DBG("\nunresolved imports\nexit\n");
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"int $0x40"::"a"(-1));
|
||||||
|
};
|
||||||
|
|
||||||
|
// __asm__ __volatile__ (
|
||||||
|
// "xchgw %bx, %bx");
|
||||||
|
|
||||||
addr_t entry = nt->OptionalHeader.AddressOfEntryPoint +
|
addr_t entry = nt->OptionalHeader.AddressOfEntryPoint +
|
||||||
nt->OptionalHeader.ImageBase;
|
nt->OptionalHeader.ImageBase;
|
||||||
|
|
||||||
// __asm__ __volatile__ (
|
thr_stack->edi = 0;
|
||||||
// "call %0":: "r" (entry));
|
thr_stack->esi = 0;
|
||||||
|
thr_stack->ebp = 0;
|
||||||
while(1);
|
thr_stack->ebx = 0;
|
||||||
|
thr_stack->edx = 0;
|
||||||
|
thr_stack->ecx = 0;
|
||||||
|
thr_stack->eax = 0;
|
||||||
|
thr_stack->eip = entry;
|
||||||
|
thr_stack->cs = 0x1b;
|
||||||
|
thr_stack->eflags = EFL_IOPL3 | EFL_IF;
|
||||||
|
thr_stack->pe_sp = 0x7FFFF000 + ((u32_t)ex_stack & 0xFFF);
|
||||||
|
thr_stack->pe_ss = 0x23;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void* __stdcall user_alloc(size_t size) asm("user_alloc");
|
||||||
|
void __stdcall user_free(void *mem) asm("user_free");
|
||||||
|
|
||||||
|
dll_t* __fastcall load_dll(const char *path)
|
||||||
|
{
|
||||||
|
PIMAGE_DOS_HEADER dos;
|
||||||
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
|
PIMAGE_EXPORT_DIRECTORY exp;
|
||||||
|
|
||||||
|
md_t *img_md;
|
||||||
|
|
||||||
|
size_t img_size;
|
||||||
|
addr_t img_base;
|
||||||
|
count_t img_pages;
|
||||||
|
|
||||||
|
size_t raw_size = 0;
|
||||||
|
void *raw;
|
||||||
|
|
||||||
|
DBG("\nload dll %s", path);
|
||||||
|
|
||||||
|
raw = load_file(path, &raw_size);
|
||||||
|
|
||||||
|
DBG(" raw = %x\n", raw);
|
||||||
|
|
||||||
|
if( ! raw)
|
||||||
|
{
|
||||||
|
DBG("file not found: %s\n", path);
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( ! validate_pe(raw, raw_size) )
|
||||||
|
{
|
||||||
|
DBG("invalid pe file %s\n", path);
|
||||||
|
mem_free(raw);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dos = (PIMAGE_DOS_HEADER)raw;
|
||||||
|
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||||
|
|
||||||
|
img_size = nt->OptionalHeader.SizeOfImage;
|
||||||
|
|
||||||
|
img_base = (addr_t)user_alloc(img_size);
|
||||||
|
if( !img_base)
|
||||||
|
{
|
||||||
|
mem_free(raw);
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
dll_t *dll = (dll_t*)slab_alloc(dll_slab,0); /* FIXME check */
|
||||||
|
if( !dll)
|
||||||
|
{
|
||||||
|
mem_free(raw);
|
||||||
|
user_free((void*)img_base);
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
create_image(img_base, (addr_t)raw);
|
||||||
|
|
||||||
|
mem_free(raw);
|
||||||
|
|
||||||
|
dos = (PIMAGE_DOS_HEADER)img_base;
|
||||||
|
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||||
|
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,img_base,
|
||||||
|
nt->OptionalHeader.DataDirectory[0].VirtualAddress);
|
||||||
|
|
||||||
|
dll->img_base = img_base;
|
||||||
|
dll->img_size = nt->OptionalHeader.SizeOfImage;
|
||||||
|
dll->img_md = NULL;
|
||||||
|
|
||||||
|
dll->img_hdr = nt;
|
||||||
|
dll->img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
|
||||||
|
dll->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,img_base,
|
||||||
|
nt->OptionalHeader.DataDirectory[0].VirtualAddress);
|
||||||
|
dll->img_name = strupr(MakePtr(char*, img_base, exp->Name));
|
||||||
|
|
||||||
|
list_insert(¤t_slot->dll_list, &dll->link);
|
||||||
|
|
||||||
|
return dll;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool link_pe(addr_t img_base)
|
||||||
|
{
|
||||||
|
PIMAGE_DOS_HEADER dos;
|
||||||
|
PIMAGE_NT_HEADERS32 nt;
|
||||||
|
char path[128];
|
||||||
|
|
||||||
|
int warn = 0;
|
||||||
|
|
||||||
|
/* assumed that image is valid */
|
||||||
|
|
||||||
|
dos = (PIMAGE_DOS_HEADER)img_base;
|
||||||
|
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||||
|
|
||||||
|
if(nt->OptionalHeader.DataDirectory[1].Size)
|
||||||
|
{
|
||||||
|
PIMAGE_IMPORT_DESCRIPTOR imp;
|
||||||
|
|
||||||
|
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
|
||||||
|
nt->OptionalHeader.DataDirectory[1].VirtualAddress);
|
||||||
|
|
||||||
|
while ( 1 )
|
||||||
|
{
|
||||||
|
PIMAGE_THUNK_DATA32 thunk;
|
||||||
|
|
||||||
|
PIMAGE_DOS_HEADER expdos;
|
||||||
|
PIMAGE_NT_HEADERS32 expnt;
|
||||||
|
PIMAGE_EXPORT_DIRECTORY exp;
|
||||||
|
|
||||||
|
u32_t *iat;
|
||||||
|
char *libname;
|
||||||
|
addr_t *functions;
|
||||||
|
u16_t *ordinals;
|
||||||
|
char **funcname;
|
||||||
|
|
||||||
|
dll_t *exp_dll;
|
||||||
|
|
||||||
|
if ( (imp->TimeDateStamp==0 ) && (imp->Name==0) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
libname=MakePtr(char*,imp->Name, img_base);
|
||||||
|
|
||||||
|
DBG("import from %s\n",libname);
|
||||||
|
|
||||||
|
exp_dll = find_dll(¤t_slot->dll_list, libname);
|
||||||
|
if(exp_dll != NULL)
|
||||||
|
{
|
||||||
|
DBG("find %s\n", exp_dll->img_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len = strlen(libname)+1;
|
||||||
|
|
||||||
|
memcpy(path, "/sys/lib/",9);
|
||||||
|
memcpy(&path[9],libname,len);
|
||||||
|
|
||||||
|
exp_dll = load_dll(path);
|
||||||
|
if( !exp_dll)
|
||||||
|
{
|
||||||
|
DBG("can't load %s\n", path);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exp = exp_dll->img_exp;
|
||||||
|
|
||||||
|
functions = MakePtr(DWORD*,exp->AddressOfFunctions,exp_dll->img_base);
|
||||||
|
ordinals = MakePtr(WORD*, exp->AddressOfNameOrdinals,exp_dll->img_base);
|
||||||
|
funcname = MakePtr(char**, exp->AddressOfNames,exp_dll->img_base);
|
||||||
|
|
||||||
|
thunk = MakePtr(PIMAGE_THUNK_DATA32,
|
||||||
|
imp->Characteristics, img_base);
|
||||||
|
iat= MakePtr(DWORD*,imp->FirstThunk, img_base);
|
||||||
|
|
||||||
|
while ( 1 ) // Loop forever (or until we break out)
|
||||||
|
{
|
||||||
|
PIMAGE_IMPORT_BY_NAME ord;
|
||||||
|
addr_t addr;
|
||||||
|
|
||||||
|
if ( thunk->u1.AddressOfData == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG )
|
||||||
|
{
|
||||||
|
// printf(" %4u\n", thunk->u1.Ordinal & 0xFFFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ord = MakePtr(PIMAGE_IMPORT_BY_NAME,
|
||||||
|
thunk->u1.AddressOfData, img_base);
|
||||||
|
*iat=0;
|
||||||
|
|
||||||
|
DBG("import %s", ord->Name);
|
||||||
|
|
||||||
|
if(strncmp(ord->Name,
|
||||||
|
MakePtr(char*,funcname[ord->Hint],exp_dll->img_base),32))
|
||||||
|
{
|
||||||
|
int ind;
|
||||||
|
char **names=funcname;
|
||||||
|
|
||||||
|
for(names = funcname,ind = 0;
|
||||||
|
ind < exp->NumberOfNames; names++,ind++)
|
||||||
|
{
|
||||||
|
if(!strncmp(ord->Name,MakePtr(char*,*names,exp_dll->img_base),32))
|
||||||
|
{
|
||||||
|
u16_t ordinal;
|
||||||
|
ordinal = ordinals[ind];
|
||||||
|
DBG(" \t\tat %x\n", functions[ordinal] + exp_dll->img_base);
|
||||||
|
*iat = functions[ordinal] + exp_dll->img_base;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if(ind == exp->NumberOfNames)
|
||||||
|
{
|
||||||
|
DBG(" unresolved import %s\n",ord->Name);
|
||||||
|
warn=1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG(" \tat %x\n", functions[ord->Hint] + exp_dll->img_base);
|
||||||
|
*iat = functions[ord->Hint] + exp_dll->img_base;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
thunk++; // Advance to next thunk
|
||||||
|
iat++;
|
||||||
|
}
|
||||||
|
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( !warn )
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ int __fastcall init_heap(addr_t base, size_t size)
|
|||||||
list_initialize(&lheap.used);
|
list_initialize(&lheap.used);
|
||||||
list_initialize(&sheap.used);
|
list_initialize(&sheap.used);
|
||||||
|
|
||||||
md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
|
md_slab = slab_cache_create(sizeof(md_t), 16,NULL,NULL,SLAB_CACHE_MAGDEFERRED);
|
||||||
|
|
||||||
md = (md_t*)slab_alloc(md_slab,0);
|
md = (md_t*)slab_alloc(md_slab,0);
|
||||||
|
|
||||||
|
@ -18,10 +18,11 @@ DONT_FREE_BLOCK equ 10h
|
|||||||
|
|
||||||
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
HEAP_TOP equ 0x5FC00000
|
HEAP_TOP equ 0x7FC00000
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc init_heap
|
_init_user_heap:
|
||||||
|
init_heap:
|
||||||
|
|
||||||
mov ebx,[current_slot]
|
mov ebx,[current_slot]
|
||||||
mov eax, [ebx+APPDATA.heap_top]
|
mov eax, [ebx+APPDATA.heap_top]
|
||||||
@ -46,7 +47,6 @@ proc init_heap
|
|||||||
or ecx, FREE_BLOCK
|
or ecx, FREE_BLOCK
|
||||||
mov [page_tabs+esi], ecx
|
mov [page_tabs+esi], ecx
|
||||||
ret
|
ret
|
||||||
endp
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
_UserAlloc:
|
_UserAlloc:
|
||||||
|
@ -568,13 +568,15 @@ void __fastcall core_free(addr_t frame)
|
|||||||
{
|
{
|
||||||
eflags_t efl;
|
eflags_t efl;
|
||||||
|
|
||||||
|
DBG("core free %x", frame);
|
||||||
|
|
||||||
efl = safe_cli();
|
efl = safe_cli();
|
||||||
spinlock_lock(&z_core.lock);
|
spinlock_lock(&z_core.lock);
|
||||||
zone_free(&z_core, frame>>12);
|
zone_free(&z_core, frame>>12);
|
||||||
spinlock_unlock(&z_core.lock);
|
spinlock_unlock(&z_core.lock);
|
||||||
safe_sti(efl);
|
safe_sti(efl);
|
||||||
|
|
||||||
DBG("core free %x remain %d\n", frame, z_core.free_count);
|
DBG(" remain %d\n", z_core.free_count);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ bool link_image(addr_t img_base)
|
|||||||
|
|
||||||
DBG("import from %s\n",libname);
|
DBG("import from %s\n",libname);
|
||||||
|
|
||||||
exp_dll = find_dll(libname);
|
exp_dll = find_dll(&core_dll.link, libname);
|
||||||
if(exp_dll != NULL)
|
if(exp_dll != NULL)
|
||||||
{
|
{
|
||||||
DBG("find %s\n", exp_dll->img_name);
|
DBG("find %s\n", exp_dll->img_name);
|
||||||
@ -381,8 +381,10 @@ bool link_image(addr_t img_base)
|
|||||||
{
|
{
|
||||||
if(!strncmp(ord->Name,MakePtr(char*,*names,exp_dll->img_base),32))
|
if(!strncmp(ord->Name,MakePtr(char*,*names,exp_dll->img_base),32))
|
||||||
{
|
{
|
||||||
DBG(" \tat %x\n", functions[ind] + exp_dll->img_base);
|
u16_t ordinal;
|
||||||
*iat = functions[ind] + exp_dll->img_base;
|
ordinal = ordinals[ind];
|
||||||
|
DBG(" \t\tat %x\n", functions[ordinal] + exp_dll->img_base);
|
||||||
|
*iat = functions[ordinal] + exp_dll->img_base;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -110,7 +110,7 @@ test_app_header:
|
|||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
align 4
|
||||||
proc mnt_exec stdcall file_base:dword, file_size:dword, \
|
proc mnt_exec stdcall file_base:dword, file_size:dword, \
|
||||||
path:dword, cmd_line:dword, flags:dword
|
path:dword, cmd_line:dword, flags:dword
|
||||||
|
|
||||||
@ -280,11 +280,12 @@ proc mnt_exec stdcall file_base:dword, file_size:dword, \
|
|||||||
endp
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack_page:dword
|
proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack:dword
|
||||||
|
|
||||||
locals
|
locals
|
||||||
slot dd ?
|
slot dd ?
|
||||||
slot_base dd ?
|
slot_base dd ?
|
||||||
|
pl0_stack dd ?
|
||||||
endl
|
endl
|
||||||
|
|
||||||
push ebx
|
push ebx
|
||||||
@ -309,8 +310,7 @@ proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack_page:
|
|||||||
_clear_ 256 ;clean extended information about process
|
_clear_ 256 ;clean extended information about process
|
||||||
|
|
||||||
; write application name
|
; write application name
|
||||||
lea eax, [path]
|
stdcall strrchr, [path], '/' ; now eax points to name without path
|
||||||
stdcall strrchr, eax, '/' ; now eax points to name without path
|
|
||||||
lea esi, [eax+1]
|
lea esi, [eax+1]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @F
|
jnz @F
|
||||||
@ -335,7 +335,11 @@ proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack_page:
|
|||||||
;mov eax,[hdr_mem]
|
;mov eax,[hdr_mem]
|
||||||
;mov [ebx+APPDATA.mem_size],eax
|
;mov [ebx+APPDATA.mem_size],eax
|
||||||
|
|
||||||
lea edi, [eax+OS_BASE+8192]
|
|
||||||
|
mov ecx, 1
|
||||||
|
call @core_alloc@4
|
||||||
|
lea edi, [eax+OS_BASE]
|
||||||
|
mov [pl0_stack], edi
|
||||||
|
|
||||||
mov [ebx+APPDATA.pl0_stack], edi
|
mov [ebx+APPDATA.pl0_stack], edi
|
||||||
add edi, RING0_STACK_SIZE
|
add edi, RING0_STACK_SIZE
|
||||||
@ -372,13 +376,12 @@ proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack_page:
|
|||||||
|
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
call @core_alloc@4
|
call @core_alloc@4
|
||||||
|
lea edi, [eax+OS_BASE] ; FIXME
|
||||||
|
|
||||||
add eax, OS_BASE ;FIXME
|
|
||||||
mov esi,[current_slot]
|
mov esi,[current_slot]
|
||||||
mov esi,[esi+APPDATA.cur_dir]
|
mov esi,[esi+APPDATA.cur_dir]
|
||||||
mov ecx,0x1000/4
|
mov ecx,0x1000/4
|
||||||
mov edi,eax
|
mov [ebx+APPDATA.cur_dir],edi
|
||||||
mov [ebx+APPDATA.cur_dir],eax
|
|
||||||
rep movsd
|
rep movsd
|
||||||
|
|
||||||
mov ebx, [slot]
|
mov ebx, [slot]
|
||||||
@ -409,22 +412,26 @@ proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack_page:
|
|||||||
mov eax,[Screen_Max_Y]
|
mov eax,[Screen_Max_Y]
|
||||||
mov [ecx+12],eax
|
mov [ecx+12],eax
|
||||||
|
|
||||||
mov ebx, [ex_pg_dir]
|
mov ebx, [pl0_stack]
|
||||||
add ebx, OS_BASE+8192-16
|
|
||||||
|
|
||||||
mov [ebx], dword _sys_app_entry
|
|
||||||
mov eax, [raw]
|
mov eax, [raw]
|
||||||
mov edx, [ex_stack_page]
|
lea ecx, [ebx+REG_EDI]
|
||||||
mov [ebx+8], eax
|
mov edx, [ex_stack]
|
||||||
mov [ebx+12], edx
|
|
||||||
|
mov [ebx+REG_ENTRY], dword _sys_app_entry
|
||||||
|
mov [ebx+REG_RESTART], dword _pe_restart
|
||||||
|
mov [ebx+REG_RAW], eax
|
||||||
|
mov [ebx+REG_CSTACK], ecx
|
||||||
|
mov [ebx+REG_USTACK], edx
|
||||||
|
|
||||||
|
lea ebx, [ebx+REG_ENTRY]
|
||||||
|
|
||||||
mov ecx, [slot]
|
mov ecx, [slot]
|
||||||
shl ecx, 5
|
shl ecx, 5
|
||||||
mov [ecx*8+SLOT_BASE+APPDATA.saved_esp], ebx
|
mov [ecx*8+SLOT_BASE+APPDATA.saved_esp], ebx
|
||||||
xor ebx, ebx ; process state - running
|
mov [CURRENT_TASK+ecx+TASKDATA.state], 0
|
||||||
mov [CURRENT_TASK+ecx+TASKDATA.state], bl
|
|
||||||
|
|
||||||
; DEBUGF 1,"%s",new_process_running
|
DEBUGF 1,"%s",new_process_running
|
||||||
.err:
|
.err:
|
||||||
mov [application_table_status], 0 ;unlock application_table_status mutex
|
mov [application_table_status], 0 ;unlock application_table_status mutex
|
||||||
mov eax,[process_number] ;set result
|
mov eax,[process_number] ;set result
|
||||||
@ -436,6 +443,13 @@ proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack_page:
|
|||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
align 4
|
||||||
|
_pe_restart:
|
||||||
|
xchg bx, bx
|
||||||
|
add esp, 12
|
||||||
|
popad
|
||||||
|
iretd
|
||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc get_new_process_place
|
proc get_new_process_place
|
||||||
@ -590,17 +604,23 @@ proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword
|
|||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
;addr_t __fastcall pe_app_space(size_t size);
|
||||||
align 4
|
align 4
|
||||||
_new_app_space:
|
@pe_app_space@4:
|
||||||
mov ecx, 2
|
sub esp, 16
|
||||||
|
|
||||||
|
mov [esp+4], ebx
|
||||||
|
mov [esp+8], esi
|
||||||
|
mov [esp+12], edi
|
||||||
|
|
||||||
|
lea ebx, [ecx+0x3FFFFF]
|
||||||
|
|
||||||
|
xor ecx, ecx
|
||||||
call @core_alloc@4
|
call @core_alloc@4
|
||||||
test eax, eax
|
test eax, eax
|
||||||
|
mov [esp], eax
|
||||||
jz .fail
|
jz .fail
|
||||||
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
|
|
||||||
mov edx, eax
|
|
||||||
mov ecx, 512
|
mov ecx, 512
|
||||||
lea edi, [eax + OS_BASE]
|
lea edi, [eax + OS_BASE]
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -611,21 +631,50 @@ _new_app_space:
|
|||||||
mov esi, _sys_pdbr+(HEAP_BASE shr 20)
|
mov esi, _sys_pdbr+(HEAP_BASE shr 20)
|
||||||
rep movsd
|
rep movsd
|
||||||
|
|
||||||
lea eax, [edx+PG_SW]
|
mov esi, [esp]
|
||||||
mov [edx+OS_BASE+(page_tabs shr 20)], eax
|
shr ebx, 22
|
||||||
|
.new_ptab:
|
||||||
|
xor ecx, ecx
|
||||||
|
call @core_alloc@4
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
|
||||||
add eax, 4096
|
lea edi, [eax+OS_BASE]
|
||||||
mov [edx+OS_BASE+0x7FC], eax
|
or eax, PG_UW
|
||||||
|
mov [esi+OS_BASE], eax
|
||||||
|
|
||||||
lea edi, [edx+OS_BASE+8192]
|
mov ecx, 1024
|
||||||
mov ecx, 2048
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
mov eax, edx
|
add esi, 4
|
||||||
|
dec ebx
|
||||||
|
jnz .new_ptab
|
||||||
|
|
||||||
|
xor ecx, ecx
|
||||||
|
call @core_alloc@4
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
|
||||||
|
lea edi, [eax+OS_BASE]
|
||||||
|
or eax, PG_UW
|
||||||
|
|
||||||
|
mov ebx, [esp]
|
||||||
|
lea edx, [ebx+PG_SW]
|
||||||
|
mov [ebx+OS_BASE+(0x7FC00000 shr 20)], eax
|
||||||
|
mov [ebx+OS_BASE+(page_tabs shr 20)], edx
|
||||||
|
|
||||||
|
mov ecx, 1024
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd
|
||||||
|
|
||||||
|
mov eax, ebx
|
||||||
.fail:
|
.fail:
|
||||||
pop edi
|
mov ebx, [esp+4]
|
||||||
pop esi
|
mov esi, [esp+8]
|
||||||
|
mov edi, [esp+12]
|
||||||
|
|
||||||
|
add esp, 16
|
||||||
ret
|
ret
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
|
@ -97,7 +97,7 @@ szEXPORTS db 'EXPORTS',0
|
|||||||
szIMPORTS db 'IMPORTS',0
|
szIMPORTS db 'IMPORTS',0
|
||||||
|
|
||||||
read_firstapp db '/sys/'
|
read_firstapp db '/sys/'
|
||||||
firstapp db 'LAUNCHER',0
|
firstapp db '@DESKTOP',0
|
||||||
|
|
||||||
char db '/rd/1/FONTS/CHAR.MT',0
|
char db '/rd/1/FONTS/CHAR.MT',0
|
||||||
char2 db '/rd/1/FONTS/CHAR2.MT',0
|
char2 db '/rd/1/FONTS/CHAR2.MT',0
|
||||||
@ -393,9 +393,11 @@ tmp_task_ptab rd 1
|
|||||||
|
|
||||||
default_io_map rd 1
|
default_io_map rd 1
|
||||||
|
|
||||||
LFBSize rd 1
|
LFBSize rd 1 ;8Mb hardcoded
|
||||||
|
|
||||||
stall_mcs rd 1
|
stall_mcs rd 1
|
||||||
|
|
||||||
|
_current_slot:
|
||||||
current_slot rd 1
|
current_slot rd 1
|
||||||
|
|
||||||
_display_data rd 1
|
_display_data rd 1
|
||||||
|
@ -64,9 +64,9 @@ end virtual
|
|||||||
|
|
||||||
CURSOR_SIZE equ 32
|
CURSOR_SIZE equ 32
|
||||||
|
|
||||||
OS_BASE equ 0x80000000
|
OS_BASE equ 0xE0000000
|
||||||
SLOT_BASE equ (OS_BASE+0x0080000)
|
SLOT_BASE equ (OS_BASE+0x0080000)
|
||||||
LFB_BASE equ 0xFE000000
|
LFB_BASE equ 0xDF000000
|
||||||
|
|
||||||
PG_SW equ 0x003
|
PG_SW equ 0x003
|
||||||
PG_NOCACHE equ 0x018
|
PG_NOCACHE equ 0x018
|
||||||
|
@ -188,11 +188,12 @@ typedef struct
|
|||||||
u32_t img_map[8]; /* mapped treads */
|
u32_t img_map[8]; /* mapped treads */
|
||||||
}dll_t;
|
}dll_t;
|
||||||
|
|
||||||
|
extern dll_t core_dll;
|
||||||
|
|
||||||
#define MakePtr( cast, ptr, addValue ) (cast)( (addr_t)(ptr) + (addr_t)(addValue) )
|
#define MakePtr( cast, ptr, addValue ) (cast)( (addr_t)(ptr) + (addr_t)(addValue) )
|
||||||
|
|
||||||
|
|
||||||
dll_t * find_dll(const char *name);
|
dll_t * find_dll(link_t *list, const char *name);
|
||||||
|
|
||||||
|
|
||||||
md_t* __fastcall load_image(const char *path);
|
md_t* __fastcall load_image(const char *path);
|
||||||
|
@ -129,13 +129,18 @@ public _rd_fat_end
|
|||||||
public _rd_root
|
public _rd_root
|
||||||
public _rd_root_end
|
public _rd_root_end
|
||||||
|
|
||||||
|
public _current_slot
|
||||||
|
|
||||||
public _load_file@4
|
public _load_file@4
|
||||||
|
|
||||||
public mnt_exec
|
public mnt_exec
|
||||||
|
|
||||||
public _new_app_space
|
public @pe_app_space@4
|
||||||
public pe_app_param
|
public pe_app_param
|
||||||
|
public _init_user_heap
|
||||||
|
|
||||||
|
public user_alloc
|
||||||
|
public user_free
|
||||||
public _strncmp@12
|
public _strncmp@12
|
||||||
|
|
||||||
public _LoadFile ; stdcall export
|
public _LoadFile ; stdcall export
|
||||||
|
@ -25,7 +25,7 @@ SECTIONS
|
|||||||
{
|
{
|
||||||
*(.edata)
|
*(.edata)
|
||||||
_code_end = .;
|
_code_end = .;
|
||||||
. = ALIGN(4096);
|
. = ALIGN(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
__edata = . - 0xE0000000;
|
__edata = . - 0xE0000000;
|
||||||
|
@ -10,8 +10,8 @@ CFLAGS = -c -O2 -I $(INCLUDE) -fomit-frame-pointer -fno-builtin
|
|||||||
LDFLAGS = -shared -s -Map kernel.map --image-base 0x100000 --file-alignment 32
|
LDFLAGS = -shared -s -Map kernel.map --image-base 0x100000 --file-alignment 32
|
||||||
|
|
||||||
KERNEL_SRC:= \
|
KERNEL_SRC:= \
|
||||||
kernel.asm \
|
kernel.asm \
|
||||||
data32.inc \
|
data32.inc \
|
||||||
core/memory.inc \
|
core/memory.inc \
|
||||||
core/heap.inc \
|
core/heap.inc \
|
||||||
core/malloc.inc \
|
core/malloc.inc \
|
||||||
@ -20,8 +20,10 @@ KERNEL_SRC:= \
|
|||||||
core/sys32.inc \
|
core/sys32.inc \
|
||||||
core/dll.inc \
|
core/dll.inc \
|
||||||
core/exports.inc \
|
core/exports.inc \
|
||||||
fs/ntfs.inc \
|
fs/ntfs.inc \
|
||||||
|
gui/window.inc \
|
||||||
gui/event.inc \
|
gui/event.inc \
|
||||||
|
video/vesa20.inc \
|
||||||
video/cursors.inc
|
video/cursors.inc
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,18 +6,18 @@ BYTE equ byte
|
|||||||
PTR equ
|
PTR equ
|
||||||
|
|
||||||
_putc:
|
_putc:
|
||||||
mov ecx, DWORD PTR [esp+4]
|
mov ecx, DWORD PTR [esp+4]
|
||||||
.L13:
|
.L13:
|
||||||
mov edx, 1021
|
mov edx, 0x3FD
|
||||||
in al, dx
|
in al, dx
|
||||||
test al, 96
|
test al, 96
|
||||||
je .L13
|
je .L13
|
||||||
mov dl, -8
|
mov dl, -8
|
||||||
mov eax, ecx
|
mov eax, ecx
|
||||||
out dx, al
|
out dx, al
|
||||||
cmp ecx, 10
|
cmp ecx, 10
|
||||||
jne .L7
|
jne .L7
|
||||||
mov cl, 13
|
mov cl, 13
|
||||||
jmp .L13
|
jmp .L13
|
||||||
.L7:
|
.L7:
|
||||||
ret
|
ret
|
||||||
|
Loading…
Reference in New Issue
Block a user