/kernel/trunk/core/fpu.inc |
---|
0,0 → 1,62 |
iglobal |
prev_user_of_fpu dd 0x1 ; set to OS |
endg |
label fpu_tss at 0xB080 |
label fpu_stack dword at 0xB060 |
align 4 |
fpu_handler: |
; clear TS flag in CR0 -> for task switching |
clts |
; save FPU context of the previous task |
mov eax,[prev_user_of_fpu] |
shl eax,8 |
add eax,0x80000+0x10 |
fsave [eax] |
; next task switch save our FPU context |
; now restore context of current task (if exists) |
mov eax,[0x3000] |
mov [prev_user_of_fpu],eax |
shl eax,8 |
add eax,0x80000 |
cmp [eax+0x7f],byte 0 |
je bs7_first_fpu |
frstor [eax+0x10] |
bs7_first_fpu: |
mov [eax+0x7f],byte 1 |
; prepare structure in stack for proper IRET |
movzx eax,word [fpu_tss+l.ss-tss_sceleton] ; push ss |
push eax |
mov eax,[fpu_tss+l.esp-tss_sceleton] ; push esp |
push eax |
mov eax,[fpu_tss+l.eflags-tss_sceleton] ; push eflags |
push eax |
movzx eax,word [fpu_tss+l.cs-tss_sceleton] ; push cs |
push eax |
mov eax,[fpu_tss+l.eip-tss_sceleton] ; push eip |
push eax |
; save eax |
push dword [fpu_tss+l.eax-tss_sceleton] |
; restore all segment registers |
mov ax,[fpu_tss+l.es-tss_sceleton] |
mov es,ax |
mov ax,[fpu_tss+l.fs-tss_sceleton] |
mov fs,ax |
mov ax,[fpu_tss+l.gs-tss_sceleton] |
mov gs,ax |
mov ax,[fpu_tss+l.ds-tss_sceleton] |
mov ds,ax |
; restore eax |
pop eax |
iret |
/kernel/trunk/core/mem.inc |
---|
0,0 → 1,473 |
if ~defined mem_inc |
mem_inc_fix: |
mem_inc fix mem_inc_fix |
;include "memmanag.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;High-level memory management in MenuetOS. |
;;It uses memory manager in memmanager.inc |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
second_base_address=0xC0000000 |
std_application_base_address=0x10000000 |
general_page_table_ dd 0 |
general_page_table=general_page_table_+second_base_address |
;----------------------------------------------------------------------------- |
create_general_page_table: |
;input |
; none |
;output |
; none |
;Procedure create general page directory and write |
;it address to [general_page_table]. |
pushad |
mov eax,1 ;alloc 1 page |
mov ebx,general_page_table ;write address to [general_page_table] |
call MEM_Alloc_Pages ;allocate page directory |
mov eax,[general_page_table] |
call MEM_Get_Linear_Address ;eax - linear address of page directory |
mov edi,eax |
mov ebx,eax |
xor eax,eax |
mov ecx,4096/4 |
cld |
rep stosd ;clear page directory |
mov eax,4 |
mov edx,eax |
call MEM_Alloc_Pages ;alloc page tables for 0x0-0x1000000 region |
cmp eax,edx |
jnz $ ;hang if not enough memory |
;fill page tables |
xor esi,esi |
mov ebp,7 |
.loop: |
;esi - number of page in page directory |
;ebp - current page address |
;ebx - linear address of page directory |
mov eax,[ebx+4*esi] |
add dword [ebx+4*esi],7 ;add flags to address of page table |
call MEM_Get_Linear_Address |
;eax - linear address of page table |
mov ecx,4096/4 |
;ecx (counter) - number of pages in page table |
;current address=4Mb*esi |
cmp esi,2 |
jz .start_lfb_map ;lfb map begin at 0x800000 |
cmp esi,3 |
jz .end_lfb_map ;lfb map end at 0xC00000 |
jmp .loop1 |
.start_lfb_map: |
;current address=lfb address |
mov ebp,[0x2f0000+0x9018] |
add ebp,7 ;add flags |
jmp .loop1 |
.end_lfb_map: |
;current address=linear address |
mov ebp,12*0x100000+7 |
.loop1: |
mov [eax],ebp ;write page address (with flags) in page table |
add eax,4 |
add ebp,4096 ;size of page=4096 bytes |
loop .loop1 |
inc esi ;next page directory entry |
cmp esi,edx |
jnz .loop |
;map region 0x80000000-0x803fffff to 0x800000-0xcfffff |
mov eax,1 ;size of the region is 4Mb so only 1 page table needed |
mov edx,ebx ;ebx still contains linear address of the page directory |
add ebx,0x800 |
call MEM_Alloc_Pages ;alloc page table for the region |
mov eax,[ebx] |
add dword [ebx],7 ;add flags |
call MEM_Get_Linear_Address ;get linear address of the page table |
mov ebx,eax |
mov ecx,4096/4 ;number of pages in page table |
mov eax,8*0x100000+7 |
.loop3: |
;ebx - linear address of page table |
;eax - current linear address with flags |
mov [ebx],eax |
add ebx,4 |
add eax,4096 |
loop .loop3 |
;map region 0xC0000000-* to 0x0-* |
mov esi,edx ;esi=linear address of the page directory |
lea edi,[esi+(second_base_address shr 20)];add offset of entry (0xC00) |
mov ecx,4 |
rep movsd ;first 16Mb of the region mapped as 0x0-0x1000000 block |
mov eax,[0xfe8c] ;eax=memory size |
add eax,0x3fffff |
shr eax,22 |
mov esi,eax ;calculate number of entries in page directory |
sub esi,4 ;subtract entries for first 16Mb. |
mov ebp,0x1000000+7 ;start physical address with flags |
;mapping memory higher than 16Mb |
.loop4: |
;esi (counter) - number of entries in page directory |
;edi - address of entry |
test esi,esi |
jle .loop4end |
call MEM_Alloc_Page ;alloc page table for entry in page directory |
mov [edi],eax |
add dword [edi],7 ;write physical address of page table in page directory |
add edi,4 ;move entry pointer |
call MEM_Get_Linear_Address |
mov ecx,eax |
xor edx,edx |
.loop5: |
;ecx - linear address of page table |
;edx - index of page in page table |
;ebp - current mapped physical address with flags |
mov [ecx+4*edx],ebp ;write address of page in page table |
add ebp,0x1000 ;move to next page |
inc edx |
cmp edx,4096/4 |
jl .loop5 |
dec esi |
jmp .loop4 |
.loop4end: |
.set_cr3: |
;set value of cr3 register to the address of page directory |
mov eax,[general_page_table] |
add eax,8+16 ;add flags |
mov cr3,eax ;now we have full access paging |
popad |
ret |
;----------------------------------------------------------------------------- |
simple_clone_cr3_table: |
;Parameters: |
; eax - physical address of cr3 table (page directory) |
;result: |
; eax - physical address of clone of cr3 table. |
;Function copy only page directory. |
push ecx |
push edx |
push esi |
push edi |
call MEM_Get_Linear_Address |
;eax - linear address of cr3 table |
mov esi,eax |
call MEM_Alloc_Page |
test eax,eax |
jz .failed |
;eax - physical address of new page diretory |
mov edx,eax |
call MEM_Get_Linear_Address |
mov edi,eax |
mov ecx,4096/4 |
cld |
;esi - address of old page directory |
;edi - address of new page directory |
rep movsd ;copy page directory |
mov eax,edx |
.failed: |
pop edi |
pop esi |
pop edx |
pop ecx |
ret |
;----------------------------------------------------------------------------- |
create_app_cr3_table: |
;Parameters: |
; eax - slot of process (index in 0x3000 table) |
;result: |
; eax - physical address of table. |
;This function create page directory for new process and |
;write it physical address to offset 0xB8 of extended |
;process information. |
push ebx |
mov ebx,eax |
mov eax,[general_page_table] |
call simple_clone_cr3_table ;clone general page table |
shl ebx,8 |
mov [second_base_address+0x80000+ebx+0xB8],eax ;save address of page directory |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
get_cr3_table: |
;Input: |
; eax - slot of process |
;result: |
; eax - physical address of page directory |
shl eax,8 ;size of process extended information=256 bytes |
mov eax,[second_base_address+0x80000+eax+0xB8] |
ret |
;----------------------------------------------------------------------------- |
dispose_app_cr3_table: |
;Input: |
; eax - slot of process |
;result: |
; none |
;This procedure frees page directory, |
;page tables and all memory of process. |
pushad |
mov ebp,eax |
;ebp = process slot in the procedure. |
shl eax,8 |
mov eax,[second_base_address+0x80000+eax+0xB8] |
mov ebx,eax |
;ebx = physical address of page directory |
call MEM_Get_Linear_Address |
mov edi,eax |
;edi = linear address of page directory |
mov eax,[edi+(std_application_base_address shr 20)] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov esi,eax |
;esi = linear address of first page table |
;search threads |
; mov ecx,0x200 |
xor edx,edx |
mov eax,0x2 |
.loop: |
;eax = current slot of process |
mov ecx,eax |
shl ecx,5 |
cmp byte [second_base_address+0x3000+ecx+0xa],0 ;if process running? |
jnz .next ;slot empty or process is terminating - go to next slot |
shl ecx,3 |
cmp [second_base_address+0x80000+ecx+0xB8],ebx ;compare page directory addresses |
jnz .next |
inc edx ;thread found |
.next: |
inc eax |
cmp eax,[0x3004] ;exit loop if we look through all processes |
jle .loop |
;edx = number of threads |
;our process is zombi so it isn't counted |
test edx,edx |
jnz .threadsexists |
;if there isn't threads then clear memory. |
add edi,std_application_base_address shr 20 |
.loop1: |
;edi = linear address of current directory entry |
;esi = linear address of current page table |
test esi,esi |
jz .loop1end |
xor ecx,ecx |
.loop2: |
;ecx = index of page |
mov eax,[esi+4*ecx] |
test eax,eax |
jz .loopend ;skip empty entries |
and eax,not (4096-1) ;clear flags |
push ecx |
call MEM_Free_Page ;free page |
pop ecx |
.loopend: |
inc ecx |
cmp ecx,1024 ;there are 1024 pages in page table |
jl .loop2 |
mov eax,esi |
call MEM_Free_Page_Linear ;free page table |
.loop1end: |
add edi,4 ;move to next directory entry |
mov eax,[edi] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov esi,eax ;calculate linear address of new page table |
test edi,0x800 |
jz .loop1 ;test if we at 0x80000000 address? |
and edi,not (4096-1) ;clear offset of page directory entry |
mov eax,edi |
call MEM_Free_Page_Linear ;free page directory |
popad |
ret |
.threadsexists: ;do nothing |
popad ;last thread will free memory |
ret |
;----------------------------------------------------------------------------- |
mem_alloc_specified_region: |
;eax - linear directory address |
;ebx - start address (aligned to 4096 bytes) |
;ecx - size in pages |
;result: |
; eax=1 - ok |
; eax=0 - failed |
;Try to alloc and map ecx pages to [ebx;ebx+4096*ecx) interval. |
pushad |
mov ebp,ebx ;save start address for recoil |
mov esi,eax |
.gen_loop: |
;esi = linear directory address |
;ebx = current address |
;ecx = remaining size in pages |
mov edx,ebx |
shr edx,22 |
mov edi,[esi+4*edx] ;find directory entry for current address |
test edi,edi |
jnz .table_exists ;check if page table allocated |
call MEM_Alloc_Page ;alloc page table |
test eax,eax |
jz .failed |
mov [esi+4*edx],eax |
add dword [esi+4*edx],7 ;write it address with flags |
call MEM_Get_Linear_Address |
call mem_fill_page ;clear page table |
jmp .table_linear |
.table_exists: |
;calculate linear address of page table |
mov eax,edi |
and eax,not (4096-1) ;clear flags |
call MEM_Get_Linear_Address |
.table_linear: |
;eax = linear address of page table |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;calculate index in page table |
mov edi,eax |
.loop: |
;edi = linear address of page table |
;edx = current page table index |
;ecx = remaining size in pages |
;ebx = current address |
test ecx,ecx |
jle .endloop1 ;all requested pages allocated |
call MEM_Alloc_Page ;alloc new page |
test eax,eax |
jz .failed |
mov [edi+4*edx],eax |
add dword [edi+4*edx],7 ;write it address with flags |
call MEM_Get_Linear_Address |
call mem_fill_page ;clear new page |
;go to next page table entry |
dec ecx |
add ebx,4096 |
inc edx |
test edx,(1024-1) |
jnz .loop |
jmp .gen_loop |
.endloop1: |
popad |
mov eax,1 ;ok |
ret |
.failed: |
;calculate data for recoil |
sub ebx,ebp |
shr ebx,12 |
mov ecx,ebx ;calculate number of allocated pages |
mov eax,esi ;restore linear address of page directory |
mov ebx,ebp ;restore initial address |
call mem_free_specified_region ;free all allocated pages |
popad |
xor eax,eax ;fail |
ret |
;----------------------------------------------------------------------------- |
mem_fill_page: |
;Input: |
; eax - address |
;result: |
; none |
;set to zero 4096 bytes at eax address. |
push ecx |
push edi |
mov edi,eax |
mov ecx,4096/4 |
xor eax,eax |
rep stosd |
lea eax,[edi-4096] |
pop edi |
pop ecx |
ret |
;----------------------------------------------------------------------------- |
mem_free_specified_region: |
;eax - linear page directory address |
;ebx - start address (aligned to 4096 bytes) |
;ecx - size in pages |
;result - none |
;Free pages in [ebx;ebx+4096*ecx) region. |
pushad |
mov esi,eax |
xor ebp,ebp |
.gen_loop: |
;esi = linear page directory address |
;ebx = current address |
;ecx = remaining pages |
;ebp = 0 for first page table |
; 1 otherwise |
mov edx,ebx |
shr edx,22 |
mov eax,[esi+4*edx] ;find directory entry for current address |
and eax,not (4096-1) |
test eax,eax |
jnz .table_exists |
;skip absent page tables |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;edx - index of current page |
add ebx,1 shl 22 |
add ecx,edx |
and ebx,not ((1 shl 22)-1) |
mov ebp,1 ;set flag |
sub ecx,1024 ;ecx=ecx-(1024-edx) |
jg .gen_loop |
popad |
ret |
.table_exists: |
call MEM_Get_Linear_Address |
;eax - linear address of table |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;edx - index of current page |
mov edi,eax |
.loop: |
;edi = linear address of page table entry |
;edx = index of page table entry |
;ecx = remaining pages |
test ecx,ecx |
jle .endloop1 |
mov eax,[edi+4*edx] |
and eax,not (4096-1) |
call MEM_Free_Page ;free page |
mov dword [edi+4*edx],0 ;and clear page table entry |
dec ecx |
inc edx |
cmp edx,1024 |
jl .loop |
test ebp,ebp |
jz .first_page |
mov eax,edi |
call MEM_Free_Page_Linear ;free page table |
mov edx,ebx |
shr edx,22 |
mov dword [esi+4*edx],0 ;and clear page directory entry |
.first_page: |
add ebx,1 shl 22 |
and ebx,not ((1 shl 22)-1) ;calculate new current address |
mov ebp,1 ;set flag |
jmp .gen_loop |
.endloop1: |
popad |
ret |
end if |
/kernel/trunk/core/memmanag.inc |
---|
0,0 → 1,977 |
if ~defined memmanager_inc |
memmanager_inc_fix: |
memmanager_inc fix memmanager_inc_fix |
;for testing in applications |
if defined B32 |
iskernel=1 |
else |
iskernel=0 |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; Memory allocator for MenuetOS kernel |
;; Andrey Halyavin, halyavin@land.ru 2005 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; heap block structure - |
;; you can handle several ranges of |
;; pages simultaneosly. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.heap_linear_address equ 0 |
.heap_block_size equ 4 |
.heap_physical_address equ 8 |
.heap_reserved equ 12 |
.heap_block_info equ 16 |
max_heaps equ 8 |
.range_info equ 36 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; memory manager data |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_heap_block_ rd .heap_block_info*max_heaps/4 |
MEM_heap_block=MEM_heap_block_+second_base_address |
MEM_heap_count_ rd 1 |
MEM_heap_count=MEM_heap_count_+second_base_address |
if iskernel = 0 |
MEM_general_mutex rd 1 |
MEM_call_count rd 1 |
MEM_mutex_pid rd 1 |
MEM_mutex_count rd 1 |
else |
MEM_cli_count_ rd 1 |
MEM_cli_count=MEM_cli_count_+second_base_address |
MEM_cli_prev_ rd 1 |
MEM_cli_prev=MEM_cli_prev_+second_base_address |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Init |
;;Initialize memory manager structures. |
;;Must be called first. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Init: |
push eax |
xor eax,eax |
if iskernel = 0 |
mov [MEM_heap_count],eax |
mov [MEM_general_mutex],eax |
mov [MEM_call_count],eax |
mov [MEM_mutex_pid],eax |
mov [MEM_mutex_count],eax |
else |
mov [MEM_cli_prev],eax ;init value = 0 |
dec eax |
mov [MEM_cli_count],eax ;init value = -1 |
end if |
pop eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;change_task |
;;procedure for changing tasks. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if iskernel = 0 |
change_task: |
push eax |
push ebx |
mov eax,5 |
xor ebx,ebx |
inc ebx |
int 0x40 |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_get_pid |
;;determine current pid |
;;result: |
;; eax - pid |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if iskernel = 0 |
MEM_get_pid: |
push ebx |
push ecx |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov eax,[esp+30] |
add esp,1024 |
pop ecx |
pop ebx |
ret |
else |
; pid_address dd 0x3000 |
;MEM_get_pid: |
; mov eax,[pid_address] |
; mov eax,[eax] |
; ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_Lock |
;;Wait until all operations with heap will be finished. |
;;Between MEM_Heap_Lock and MEM_Heap_UnLock operations |
;;with heap are forbidden. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_Lock: |
if iskernel = 0 |
push eax |
inc dword [MEM_call_count] |
MEM_Heap_Lock_wait: |
mov eax,1 |
xchg [MEM_general_mutex],eax |
test eax,eax |
jz MEM_Heap_Lock_end |
call MEM_get_pid |
cmp [MEM_mutex_pid],eax |
jz MEM_Heap_Lock_end1 |
call change_task |
jmp MEM_Heap_Lock_wait |
MEM_Heap_Lock_end1: |
inc dword [MEM_mutex_count] |
pop eax |
ret |
MEM_Heap_Lock_end: |
call MEM_get_pid |
mov [MEM_mutex_pid],eax |
mov dword [MEM_mutex_count],1 |
pop eax |
ret |
else |
pushfd |
cli |
inc dword [MEM_cli_count] |
jz MEM_Heap_First_Lock |
add esp,4 |
ret |
MEM_Heap_First_Lock: ;save interrupt flag |
shr dword [esp],9 |
and dword [esp],1 |
pop dword [MEM_cli_prev] |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_UnLock |
;;After this routine operations with heap are allowed. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_UnLock: |
if iskernel = 0 |
push eax |
xor eax,eax |
dec dword [MEM_mutex_count] |
jnz MEM_Heap_UnLock_No_Wait1 |
dec dword [MEM_call_count] |
mov [MEM_mutex_pid],eax |
mov [MEM_general_mutex],eax;release mutex BEFORE task switching |
jz MEM_Heap_UnLock_No_Wait |
call change_task ;someone want to use heap - switch tasks |
MEM_Heap_UnLock_No_Wait: |
pop eax |
ret |
MEM_Heap_UnLock_No_Wait1: |
dec dword [MEM_call_count] |
jz MEM_Heap_UnLock_No_Wait2 |
call change_task |
MEM_Heap_UnLock_No_Wait2: |
pop eax |
ret |
else |
dec dword [MEM_cli_count] |
js MEM_Heap_UnLock_last |
ret |
MEM_Heap_UnLock_last: |
cmp dword [MEM_cli_prev],0 ;restore saved interrupt flag |
jz MEM_Heap_UnLock_No_sti |
sti |
MEM_Heap_UnLock_No_sti: |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Heap |
;;Add new range to memory manager. |
;;eax - linear address |
;;ebx - size in pages |
;;ecx - physical address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Add_Heap: |
push edx |
call MEM_Heap_Lock |
mov edx,[MEM_heap_count] |
cmp edx,max_heaps |
jz MEM_Add_Heap_Error |
inc dword [MEM_heap_count] |
shl edx,4 |
mov [MEM_heap_block+edx+.heap_linear_address],eax |
mov [MEM_heap_block+edx+.heap_block_size],ebx |
shl dword [MEM_heap_block+edx+.heap_block_size],12 |
mov [MEM_heap_block+edx+.heap_physical_address],ecx |
lea edx,[4*ebx+.range_info+4095] ;calculate space for page info table |
and edx,0xFFFFF000 |
mov [eax],eax |
add [eax],edx ;first 4 bytes - pointer to first free page |
;clean page info area |
push edi |
lea edi,[eax+4] |
mov ecx,edx |
shr ecx,2 |
push eax |
xor eax,eax |
rep stosd |
pop eax |
pop edi |
;create free pages list. |
mov ecx,[eax] |
shl ebx,12 |
add eax,ebx ;eax - address after block |
MEM_Add_Heap_loop: |
add ecx,4096 |
mov [ecx-4096],ecx ;set forward pointer |
cmp ecx,eax |
jnz MEM_Add_Heap_loop |
mov dword [ecx-4096],0 ;set end of list |
MEM_Add_Heap_ret: |
call MEM_Heap_UnLock |
pop edx |
ret |
MEM_Add_Heap_Error: |
xor eax,eax |
jmp MEM_Add_Heap_ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Physical_Address |
;;Translate linear address to physical address |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax - physical address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Physical_Address |
MEM_Get_Physical_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Physical_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Physical_Address_next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Physical_Address_next |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Get_Physical_Address_loopend |
MEM_Get_Physical_Address_next: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Physical_Address_loop |
xor eax,eax ;address not found |
MEM_Get_Physical_Address_loopend: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Linear_Address |
;;Translate physical address to linear address. |
;;Parameters: |
;; eax - physical address |
;;Result: |
;; eax - linear address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Linear_Address |
MEM_Get_Linear_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Linear_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Linear_Address_Next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Linear_Address_Next |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
pop ecx |
ret |
MEM_Get_Linear_Address_Next: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Linear_Address_loop |
call MEM_Heap_UnLock |
pop ecx |
xor eax,eax ;address not found |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - physical address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page |
MEM_Alloc_Page: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
sub eax,ecx |
push eax |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Alloc_Page_ret |
MEM_Alloc_Page_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_loop |
xor eax,eax |
MEM_Alloc_Page_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page_Linear |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - linear address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page_Linear |
MEM_Alloc_Page_Linear: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_Linear_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_Linear_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
push eax |
sub eax,ecx |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
jmp MEM_Alloc_Page_Linear_ret |
MEM_Alloc_Page_Linear_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_Linear_loop |
xor eax,eax |
MEM_Alloc_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - physical address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page |
MEM_Free_Page: |
test eax,eax |
jz MEM_Free_Page_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
js MEM_Free_Page_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Heap_loopend |
MEM_Free_Page_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Free_Page_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Bucket |
test dx,dx |
jz MEM_Free_Page_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_OK |
MEM_Free_Page_Bucket: |
push dword [ecx] |
mov [ecx],eax |
pop dword [eax] |
mov dword [ecx+.range_info+ebx],0 |
MEM_Free_Page_OK: |
mov eax,1 |
MEM_Free_Page_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Page_Error: |
xor eax,eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Zero: |
inc eax |
ret |
MEM_Free_Page_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page_Linear |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - linear address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page_Linear |
MEM_Free_Page_Linear: |
test eax,eax |
jz MEM_Free_Page_Linear_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Linear_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Linear_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
js MEM_Free_Page_Linear_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Linear_Heap_loopend |
MEM_Free_Page_Linear_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Free_Page_Linear_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_Linear_ret |
MEM_Free_Page_Linear_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Linear_Bucket |
test dx,dx |
jz MEM_Free_Page_Linear_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_Linear_OK |
MEM_Free_Page_Linear_Bucket: |
mov edx,[ecx] |
mov [eax],edx |
mov dword [eax+4],0 |
mov [ecx],eax |
test edx,edx |
jz MEM_Free_Page_No_Next |
mov [edx+4],eax |
MEM_Free_Page_No_Next: |
mov dword [ecx+.range_info+ebx],0 |
MEM_Free_Page_Linear_OK: |
xor eax, eax |
inc eax |
MEM_Free_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Page_Linear_Error: |
xor eax,eax |
jmp MEM_Free_Page_Linear_ret |
MEM_Free_Page_Linear_Zero: |
inc eax |
ret |
MEM_Free_Page_Linear_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for physical addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages |
MEM_Alloc_Pages: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_ret |
MEM_Alloc_Pages_loop: |
call MEM_Alloc_Page |
test eax,eax |
jz MEM_Alloc_Pages_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_loop |
MEM_Alloc_Pages_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages_Linear |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for linear addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages_Linear |
MEM_Alloc_Pages_Linear: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_Linear_ret |
MEM_Alloc_Pages_Linear_loop: |
call MEM_Alloc_Page_Linear |
test eax,eax |
jz MEM_Alloc_Pages_Linear_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_Linear_loop |
MEM_Alloc_Pages_Linear_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages |
MEM_Free_Pages: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_ret |
MEM_Free_Pages_loop: |
mov eax,[ebx] |
call MEM_Free_Page |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_ret |
dec ecx |
jnz MEM_Free_Pages_loop |
MEM_Free_Pages_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages_Linear |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages_Linear |
MEM_Free_Pages_Linear: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_Linear_ret |
MEM_Free_Pages_Linear_loop: |
mov eax,[ebx] |
call MEM_Free_Page_Linear |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_Linear_ret |
dec ecx |
jnz MEM_Free_Pages_Linear_loop |
MEM_Free_Pages_Linear_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number |
MEM_Get_Heap_Number: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_loopend |
MEM_Get_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Heap_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_loopend: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number_Linear |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number_Linear |
MEM_Get_Heap_Number_Linear: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_Linear_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Heap_Linear_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_Linear_loopend |
MEM_Get_Heap_Linear_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Heap_Linear_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_Linear_loopend: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc |
;;Allocate small region. |
;;Parameters: |
;; eax - size (0<eax<=4096) |
;;Result: |
;; eax - linear address |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc |
MEM_Alloc: |
;find chain |
test eax,eax |
jng MEM_Alloc_Wrong_Size |
cmp eax,4096 |
jg MEM_Alloc_Wrong_Size |
push ebx |
push ecx |
push edx |
push esi |
dec eax |
shr eax,4 |
xor edx,edx |
MEM_Alloc_Find_Size: |
add edx,4 |
shr eax,1 |
jnz MEM_Alloc_Find_Size |
MEM_Alloc_Size_Found: |
mov ecx,edx |
shr ecx,2 |
add ecx,4 |
mov eax,1 |
shl eax,cl |
mov esi,eax |
;esi - block size |
;edx - offset |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Find_Heap: |
mov eax,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [eax+edx],0 |
jnz MEM_Alloc_Use_Existing |
sub ecx,16 |
jns MEM_Alloc_Find_Heap |
;create new bucket page |
call MEM_Alloc_Page_Linear |
call MEM_Get_Heap_Number_Linear |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov [ecx+edx],eax |
lea ebx,[eax+4096] |
MEM_Alloc_List_loop: |
mov [eax],eax |
mov [eax+4],eax |
add [eax],esi |
sub [eax+4],esi |
add eax,esi |
cmp eax,ebx |
jnz MEM_Alloc_List_loop |
sub ebx,esi |
mov dword [ebx],0 |
sub eax,4096 |
mov dword [eax+4],0 |
mov eax,ecx |
MEM_Alloc_Use_Existing: |
mov ebx,eax |
mov eax,[eax+edx] |
mov ecx,[eax] |
mov [ebx+edx],ecx |
test ecx,ecx |
jz MEM_Alloc_Became_Empty |
mov dword [ecx+4],0 |
MEM_Alloc_Became_Empty: |
mov ecx,eax |
sub ecx,ebx |
shr ecx,10 |
and ecx,0xFFFFFFFC |
inc byte [ebx+.range_info+ecx+2] |
shr edx,2 |
add edx,128 |
dec edx |
mov [ebx+.range_info+ecx+3],dl |
MEM_Alloc_ret: |
call MEM_Heap_UnLock |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Alloc_Wrong_Size: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free |
MEM_Free: |
test eax,eax |
jz MEM_Free_Zero |
push ebx |
push ecx |
push edx |
push esi |
push edi |
push ebp |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Free_ret |
mov edx,eax |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub edx,ecx |
shr edx,10 |
and edx,0xFFFFFFFC |
mov ebx,[ecx+.range_info+edx] |
mov esi,ebx |
shr esi,24 |
sub esi,128 |
mov edi,[ecx+4+4*esi] |
mov [eax],edi |
mov dword [eax+4],0 |
test edi,edi |
jz MEM_Free_Empty_List |
mov [edi+4],eax |
MEM_Free_Empty_List: |
mov [ecx+4+4*esi],eax |
sub ebx,0x10000 |
mov [ecx+.range_info+edx],ebx |
test ebx,0xFF0000 |
jnz MEM_Free_ret |
;delete empty blocks on the page |
lea edx,[esi+5] |
and eax,0xFFFFF000 |
mov edi,eax |
mov eax,1 |
xchg ecx,edx |
shl eax,cl |
mov ecx,edx |
mov edx,eax |
;edx - size of block |
;edi - start of page |
mov eax,edi |
lea ebx,[eax+4096] |
MEM_Free_Block_loop: |
cmp dword [eax+4],0 |
jnz MEM_Free_Block_Not_First |
mov ebp,dword [eax] |
mov [ecx+4+4*esi],ebp |
test ebp,ebp |
jz MEM_Free_Block_Last |
mov dword [ebp+4],0 |
MEM_Free_Block_Last: |
jmp MEM_Free_Block_loop_end |
MEM_Free_Block_Not_First: |
mov ebp,dword [eax] |
push ebp |
mov ebp,dword [eax+4] |
pop dword [ebp] |
mov ebp,dword [eax] |
test ebp,ebp |
jz MEM_Free_Block_loop_end |
push dword [eax+4] |
pop dword [ebp+4] |
; jmp MEM_Free_Block_loop_end |
MEM_Free_Block_loop_end: |
add eax,edx |
cmp eax,ebx |
jnz MEM_Free_Block_loop |
mov eax,edi |
call MEM_Free_Page_Linear |
MEM_Free_ret: |
call MEM_Heap_UnLock |
pop ebp |
pop edi |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Zero: |
inc eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference |
;; eax - physical address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference |
MEM_Add_Reference: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number |
test eax,eax |
jz MEM_Add_Reference_ret |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_failed |
inc dword [ecx+eax+.range_info] |
MEM_Add_Reference_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_failed: |
xor eax,eax |
jmp MEM_Add_Reference_ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference_Linear |
;; eax - linear address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference_Linear |
MEM_Add_Reference_Linear: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Add_Reference_Linear_ret |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub eax,ecx |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_Linear_failed |
inc dword [ecx+eax+.range_info] |
mov eax,1 |
MEM_Add_Reference_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_Linear_failed: |
xor eax,eax |
jmp MEM_Add_Reference_Linear_ret |
end if |
end if ;memmanager.inc |
/kernel/trunk/core/newproce.inc |
---|
0,0 → 1,1321 |
if ~defined newprocess_inc |
newprocess_inc_fix: |
newprocess_inc fix newprocess_inc_fix |
include "mem.inc" |
include "memmanag.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;Working with new types of processes. |
;;Author: Khalyavin Andrey halyavin@land.ru |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
new_process_loading db 'K : New Process - loading',13,10,0 |
new_process_running db 'K : New Process - done',13,10,0 |
start_not_enough_memory db 'K : New Process - not enough memory',13,10,0 |
endg |
;----------------------------------------------------------------------------- |
find_new_process_place: |
;input: |
; none |
;result: |
; eax=[new_process_place]<>0 - ok |
; 0 - failed. |
;This function find least empty slot. |
;It doesn't increase [0x3004]! |
mov eax,0x3000+second_base_address |
push ebx |
mov ebx,[0x3004] |
inc ebx |
shl ebx,5 |
add ebx,eax ;ebx - address of process information for (last+1) slot |
.newprocessplace: |
;eax = address of process information for current slot |
cmp eax,ebx |
jz .endnewprocessplace ;empty slot after high boundary |
add eax,0x20 |
cmp word [eax+0xa],9 ;check process state, 9 means that process slot is empty |
jnz .newprocessplace |
.endnewprocessplace: |
mov ebx,eax |
sub eax,0x3000+second_base_address |
shr eax,5 ;calculate slot index |
cmp eax,256 |
jge .failed ;it should be <256 |
mov word [ebx+0xa],9 ;set process state to 9 (for slot after hight boundary) |
mov [new_process_place],eax ;save process slot |
pop ebx |
ret |
.failed: |
xor eax,eax |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
new_start_application_floppy: |
;input: |
; eax - pointer to filename |
; ebx - parameters to pass |
;result: |
; eax - pid of new process |
; or 0 if call fails. |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write to debug board |
;wait application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;we can change system tables now |
push edi |
push ebx |
push eax |
call find_new_process_place ;find empty process slot |
sti |
test eax,eax |
jz .failed |
mov edi,eax |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax,eax |
cld |
rep stosd ;clean extended information about process |
;set new process name |
mov eax,[esp+8] |
.find_last_byte: |
cmp byte [eax],0 |
jz .find_last_byte_end |
inc eax |
jmp .find_last_byte |
.find_last_byte_end: |
sub eax,11 ;last 11 bytes = application name |
; mov eax,[esp] ;eax - pointer to file name |
mov ebx,[new_process_place] |
shl ebx,8 |
add ebx,0x80000 |
mov ecx,11 |
call memmove |
;read header of file |
mov eax,[esp] |
mov ebx,1 ;index of first block |
mov ecx,2 ;number of blocks |
mov edx,0x90000 ;temp area |
mov esi,12 ;file name length |
mov edi,[esp+8] |
; cli |
call floppy_fileread ;read file from FD |
; sti |
cmp eax,0 |
jne .cleanfailed |
;check MENUET signature |
cmp [0x90000],dword 'MENU' |
jnz .cleanfailed |
cmp [0x90004],word 'ET' |
jnz .cleanfailed |
call get_app_params ;parse header fields |
cmp esi,0 |
jz .cleanfailed |
mov eax,[new_process_place] |
call create_app_cr3_table ;create page directory for new process |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address ;calculate linear address of it |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4095 |
shr ecx,12 |
mov edx,eax |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
jz .cleanfailed_mem |
mov eax,[edx+(std_application_base_address shr 20)] |
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table |
call MEM_Get_Linear_Address |
mov edx,eax |
;read file |
mov ebx,1 |
mov esi,12 ;length of file name |
.loop1: |
;edx = linear address of current page table entry |
;ebx = index of current block in file |
push edx |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax ;read file block to current page |
mov eax,[esp+4] ;restore pointer to file name |
mov ecx,8 ;number of blocks read |
push ebx |
mov edi,[esp+16] |
; cli |
call floppy_fileread |
;ebx=file size |
; sti |
pop ecx |
shr ebx,9 |
cmp ecx,ebx |
jg .endloop1 ;if end of file? |
mov ebx,ecx |
test eax,eax |
jnz .endloop1 ;check io errors |
pop edx |
add ebx,8 ;go to next page |
add edx,4 |
jmp .loop1 |
.endloop1: |
add esp,8+4 ;pop linear address of page table entry and pointer to file name |
call new_start_application_fl.add_app_parameters |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem: |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
.failed: |
add esp,8+4 |
mov [application_table_status],0 |
popad |
sti |
mov eax,-1 |
ret |
;----------------------------------------------------------------------------- |
new_start_application_fl: |
;input: |
; eax - pointer to filename |
; ebx - parameters to pass |
;result: |
; eax - pid of new process |
; or 0 if call fails. |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write to debug board |
;wait application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;we can change system tables now |
push ebx |
push eax |
call find_new_process_place ;find empty process slot |
sti |
test eax,eax |
jz .failed |
mov edi,eax |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax,eax |
cld |
rep stosd ;clean extended information about process |
;set new process name |
mov eax,[esp] ;eax - pointer to file name |
mov ebx,[new_process_place] |
shl ebx,8 |
add ebx,0x80000 |
mov ecx,11 |
call memmove |
;read header of file |
mov ebx,1 ;index of first block |
mov ecx,2 ;number of blocks |
mov edx,0x90000 ;temp area |
mov esi,12 ;file name length |
cli |
call fileread ;read file from RD |
sti |
cmp eax,0 |
jne .cleanfailed |
;check MENUET signature |
cmp [0x90000],dword 'MENU' |
jnz .cleanfailed |
cmp [0x90004],word 'ET' |
jnz .cleanfailed |
call get_app_params ;parse header fields |
cmp esi,0 |
jz .failed |
mov eax,[new_process_place] |
call create_app_cr3_table ;create page directory for new process |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address ;calculate linear address of it |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4095 |
shr ecx,12 |
mov edx,eax |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
jz .cleanfailed_mem |
mov eax,[edx+(std_application_base_address shr 20)] |
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table |
call MEM_Get_Linear_Address |
mov edx,eax |
;read file |
mov ebx,1 |
mov esi,12 ;length of file name |
.loop1: |
;edx = linear address of current page table entry |
;ebx = index of current block in file |
push edx |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax ;read file block to current page |
mov eax,[esp+4] ;restore pointer to file name |
mov ecx,8 ;number of blocks read |
push ebx |
cli |
call fileread |
;ebx=file size |
sti |
pop ecx |
shr ebx,9 |
cmp ecx,ebx |
jg .endloop1 ;if end of file? |
mov ebx,ecx |
test eax,eax |
jnz .endloop1 ;check io errors |
pop edx |
add ebx,8 ;go to next page |
add edx,4 |
jmp .loop1 |
.endloop1: |
add esp,8 ;pop linear address of page table entry and pointer to file name |
call .add_app_parameters |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem: |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
.failed: |
add esp,8 |
mov [application_table_status],0 |
popad |
sti |
mov eax,-1 |
ret |
.add_app_parameters: |
;input: |
; [esp] - pointer to parameters |
; [esp+4]-[esp+36] pushad registers. |
;result |
; eax - pid of new process |
; or zero if failed |
cli |
mov ebx,[new_process_place] |
cmp ebx,[0x3004] |
jle .noinc |
inc dword [0x3004] ;update number of processes |
.noinc: |
; mov ebx,[new_process_place] |
;set 0x8c field of extended information about process |
;(size of application memory) |
shl ebx,8 |
mov eax,[app_mem] |
mov [second_base_address+0x80000+0x8c+ebx],eax |
;set 0x10 field of information about process |
;(application base address) |
; mov ebx,[new_process_place] |
; shl ebx,5 |
shr ebx,3 |
mov dword [second_base_address+0x3000+ebx+0x10],std_application_base_address |
;add command line parameters |
.add_command_line: |
mov edx,[app_i_param] |
test edx,edx |
jz .no_command_line ;application don't need parameters |
mov eax,[esp+4] |
test eax,eax |
jz .no_command_line ;no parameters specified |
;calculate parameter length |
mov esi,eax |
xor ecx,ecx |
.command_line_len: |
cmp byte [esi],0 |
jz .command_line_len_end |
inc esi |
inc ecx |
cmp ecx,256 |
jl .command_line_len |
.command_line_len_end: |
;ecx - parameter length |
;edx - address of parameters in new process address space |
mov ebx,eax ;ebx - address of parameters in our address space |
mov eax,[new_process_place] |
call write_process_memory ;copy parameters to new process address space |
.no_command_line: |
mov ebx,[new_process_place] |
mov eax,ebx |
shl ebx,5 |
add ebx,0x3000 ;ebx - pointer to information about process |
mov [ebx+0xe],al ;set window number on screen = process slot |
mov [ebx],dword 1+2+4 ;set default event flags (see 40 function) |
inc dword [process_number] |
mov eax,[process_number] |
mov [ebx+4],eax ;set PID |
mov ecx,ebx |
add ecx,draw_data-0x3000 ;ecx - pointer to draw data |
;set draw data to full screen |
mov [ecx+0],dword 0 |
mov [ecx+4],dword 0 |
mov eax,[0xfe00] |
mov [ecx+8],eax |
mov eax,[0xfe04] |
mov [ecx+12],eax |
;set cr3 register in TSS of application |
mov ecx,[new_process_place] |
shl ecx,8 |
mov eax,[0x800B8+ecx] |
add eax,8+16 ;add flags |
mov [l.cr3],eax |
;write cr3 in TSS of System Call Handler |
mov ecx,[new_process_place] |
shl ecx,7 |
mov [0x298000+ecx+l.cr3-tss_sceleton],eax ;write directy to TSS |
mov eax,[app_start] |
mov [l.eip],eax ;set eip in TSS |
mov eax,[app_esp] |
mov [l.esp],eax ;set stack in TSS |
;gdt |
mov ebx,[new_process_place] |
shl ebx,3 |
mov ax,app_code ;ax - selector of code segment |
add ax,bx |
mov [l.cs],ax |
mov ax,app_data |
add ax,bx ;ax - selector of data segment |
mov [l.ss],ax |
mov [l.ds],ax |
mov [l.es],ax |
mov [l.fs],ax |
mov ax,graph_data ;ax - selector of graphic segment |
mov [l.gs],ax |
mov [l.io],word 128 |
mov [l.eflags],dword 0x11202 |
mov [l.ss0],os_data |
mov [l.esp0],0x55000 |
; mov [l.esp1],0x56000 |
; mov [l.esp2],0x57000 |
;copy tss to it place |
mov eax,tss_sceleton |
mov ebx,[new_process_place] |
imul ebx,tss_step |
add ebx,tss_data ;ebx - address of application TSS |
mov ecx,120 |
call memmove |
;Add IO access table - bit array of permitted ports |
or eax,-1 |
mov edi,[new_process_place] |
imul edi,tss_step |
add edi,tss_data+128 |
mov ecx,2048 |
cld |
rep stosd ;full access to 2048*8=16384 ports |
mov ecx,ebx ;ecx - address of application TSS |
mov edi,[new_process_place] |
shl edi,3 |
;set TSS descriptor |
mov [edi+gdts+tss0+0],word tss_step ;limit (size) |
mov [edi+gdts+tss0+2],cx ;part of offset |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+tss0+4],al ;part of offset |
mov [edi+gdts+tss0+7],ah ;part of offset |
mov [edi+gdts+tss0+5],word 01010000b*256+11101001b ;system flags |
;set code and data segments |
mov eax,[new_process_place] |
shl eax,3 |
;set base address of code segment |
mov word [eax+gdts+app_code-3+2],0 |
mov byte [eax+gdts+app_code-3+4],0 |
mov byte [eax+gdts+app_code-3+7],std_application_base_address shr 24 |
;set limit of code segment |
; mov ebx,[app_mem] |
; add ebx,4095 |
; shr ebx,12 |
mov ebx,(0x80000000-std_application_base_address) shr 12 |
mov [eax+gdts+app_code-3+0],bx |
mov [eax+gdts+app_code-3+5],word 11010000b*256+11111010b+256*((0x80000000-std_application_base_address) shr 28) |
;set base address of data segment |
mov word [eax+gdts+app_data-3+2],0 |
mov byte [eax+gdts+app_data-3+4],0 |
mov byte [eax+gdts+app_data-3+7],std_application_base_address shr 24 |
;set limit of data segment |
mov [eax+gdts+app_data-3+0],bx |
mov [eax+gdts+app_data-3+5],word 11010000b*256+11110010b+256*((0x80000000-std_application_base_address) shr 28) |
;flush keyboard and buttons queue |
mov [0xf400],byte 0 |
mov [0xf500],byte 0 |
mov edi,[new_process_place] |
shl edi,5 |
add edi,window_data |
mov ebx,[new_process_place] |
movzx esi,word [0xC000+ebx*2] |
lea esi,[0xC400+esi*2] |
call windowactivate ;gui initialization |
mov ebx,[new_process_place] |
shl ebx,5 |
mov [0x3000+ebx+0xa],byte 0 ;set process state - running |
mov esi,new_process_running |
call sys_msg_board_str ;output information about succefull startup |
; add esp,4 ;pop pointer to parameters |
; popad |
mov eax,[process_number] ;set result |
mov [application_table_status],0 ;unlock application_table_status mutex |
sti |
ret 4 |
;----------------------------------------------------------------------------- |
new_sys_threads: |
;eax=1 - create thread |
; ebx=thread start |
; ecx=thread stack value |
;result: |
; eax=pid |
pushad |
cmp eax,1 |
jnz .ret ;other subfunctions |
mov esi,new_process_loading |
call sys_msg_board_str |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
je .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;find free process slot |
call find_new_process_place |
test eax,eax |
jz .failed |
;set parameters for thread |
xor eax,eax |
mov [app_i_param],eax |
mov [app_i_icon],eax |
mov [app_start],ebx |
mov [app_esp],ecx |
mov esi,[0x3000] |
shl esi,8 |
add esi,0x80000 |
mov ebx,esi ;ebx=esi - pointer to extended information about current thread |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov edx,edi ;edx=edi - pointer to extended infomation about new thread |
mov ecx,256/4 |
rep stosd ;clean extended information about new thread |
mov edi,edx |
mov ecx,11 |
rep movsb ;copy process name |
mov eax,[ebx+0x8c] |
mov [app_mem],eax ;set memory size |
mov eax,[ebx+0xb8] |
mov [edx+0xb8],eax ;copy page directory |
; mov eax,[new_process_place] |
; mov ebx,[0x3000] |
; call addreference_app_cr3_table |
push 0 ;no parameters |
call new_start_application_fl.add_app_parameters ;start thread |
mov [esp+28],eax |
popad |
ret |
.failed: |
sti |
popad |
mov eax,-1 |
ret |
.ret: |
popad |
ret |
;----------------------------------------------------------------------------- |
new_mem_resize: |
;input: |
; ebx - new size |
;result: |
; [esp+36]:=0 - normal |
; [esp+36]:=1 - error |
;This function set new application memory size. |
mov esi,ebx ;save new size |
add ebx,4095 |
and ebx,not (4096-1) ;round up size |
mov ecx,[0x3000] |
shl ecx,8 |
mov edx,[0x8008C+ecx] |
add edx,4095 |
and edx,not (4096-1) ;old size |
mov eax,[0x800B8+ecx] |
call MEM_Get_Linear_Address |
;eax - linear address of page directory |
call MEM_Heap_Lock ;guarantee that two threads willn't |
;change memory size simultaneously |
cmp ebx,edx |
; mov esi,ebx ;save new size |
jg .expand |
.free: |
sub edx,ebx |
jz .unlock ;do nothing |
mov ecx,edx |
shr ecx,12 |
add ebx,std_application_base_address |
call mem_free_specified_region ;free unnecessary pages |
jmp .unlock |
.expand: |
sub ebx,edx |
mov ecx,ebx |
shr ecx,12 |
mov ebx,edx |
add ebx,std_application_base_address |
call mem_alloc_specified_region ;alloc necessary pages |
test eax,eax |
jz .failed ;not enough memory |
.unlock: |
mov ebx,esi |
mov eax,[0x3000] |
shl eax,8 |
mov [eax+0x8008c],ebx ;write new memory size |
;search threads and update |
;application memory size infomation |
mov ecx,[eax+0x800b8] |
mov eax,2 |
.search_threads: |
;eax = current slot |
;ebx = new memory size |
;ecx = page directory |
cmp eax,[0x3004] |
jg .search_threads_end |
mov edx,eax |
shl edx,5 |
cmp word [0x3000+edx+0xa],9 ;if slot empty? |
jz .search_threads_next |
shl edx,3 |
cmp [edx+0x800b8],ecx ;if it is our thread? |
jnz .search_threads_next |
mov [edx+0x8008c],ebx ;update memory size |
.search_threads_next: |
inc eax |
jmp .search_threads |
.search_threads_end: |
call MEM_Heap_UnLock |
mov dword [esp+36],0 |
ret |
.failed: |
call MEM_Heap_UnLock |
mov dword [esp+36],1 |
ret |
;----------------------------------------------------------------------------- |
pid_to_slot: |
;Input: |
; eax - pid of process |
;Output: |
; eax - slot of process or 0 if process don't exists |
;Search process by PID. |
push ebx |
push ecx |
mov ebx,[0x3004] |
shl ebx,5 |
mov ecx,2*32 |
.loop: |
;ecx=offset of current process info entry |
;ebx=maximum permitted offset |
cmp byte [second_base_address+0x3000+ecx+0xa],9 |
jz .endloop ;skip empty slots |
cmp [second_base_address+0x3000+ecx+0x4],eax ;check PID |
jz .pid_found |
.endloop: |
add ecx,32 |
cmp ecx,ebx |
jle .loop |
pop ecx |
pop ebx |
xor eax,eax |
ret |
.pid_found: |
shr ecx,5 |
mov eax,ecx ;convert offset to index of slot |
pop ecx |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
is_new_process: |
;Input: |
; eax - process slot |
;Output: |
; eax=1 - it is new process |
; eax=0 - it is old process |
; shl eax,5 |
; mov eax,[second_base_address+0x3000+eax+0x10] |
; cmp eax,std_application_base_address ;check base address of application |
; jz .new_process |
; xor eax,eax |
; ret |
;.new_process: |
mov eax,1 |
ret |
;----------------------------------------------------------------------------- |
write_process_memory: |
;Input: |
; eax - process slot |
; ebx - buffer address |
; ecx - buffer size |
; edx - start address in other process |
;Output: |
; eax - number of bytes written |
pushad |
shl eax,8 |
mov eax,[0x80000+eax+0xB8] |
call MEM_Get_Linear_Address |
mov ebp,eax |
;ebp=linear address of page directory of other process. |
add edx,std_application_base_address ;convert to linear address |
test ecx,ecx |
jle .ret |
.write_loop: |
;ebx = current buffer address |
;ecx>0 = current size |
;edx = current address in other process |
;ebp = linear address of page directory |
call MEM_Heap_Lock ;cli |
mov esi,edx |
shr esi,22 |
mov eax,[ebp+4*esi] ;find page directory entry |
and eax,not (4096-1) ;clear flags |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page table |
test eax,eax |
jz .page_not_found |
mov esi,edx |
shr esi,12 |
and esi,1023 |
mov eax,[eax+4*esi] ;find page table entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page |
test eax,eax |
jz .page_not_found |
mov edi,eax |
call MEM_Add_Reference_Linear;guarantee that page willn't disappear |
call MEM_Heap_UnLock ;sti |
mov esi,edx |
and esi,4095 |
add edi,esi ;add offset in page |
;edi = linear address corresponding edx in other process |
sub esi,4096 |
neg esi ;esi - number of remaining bytes in page |
cmp esi,ecx |
jl .min_ecx |
mov esi,ecx |
.min_ecx: ;esi=min(ecx,esi) - number of bytes to write |
sub ecx,esi |
push ecx |
mov ecx,esi ;ecx - number of bytes to write |
mov esi,ebx ;esi - source, edi - destination |
add edx,ecx ;move pointer in address space of other process |
push edi |
;move ecx bytes |
test ecx,3 |
jnz .not_aligned |
shr ecx,2 |
rep movsd |
jmp .next_iter |
.not_aligned: |
rep movsb |
.next_iter: |
pop eax |
and eax,not (4096-1) ;eax - linear address of current page |
call MEM_Free_Page_Linear ;free reference |
mov ebx,esi ;new pointer to buffer - movsb automaticaly advance it. |
pop ecx ;restore number of remaining bytes |
test ecx,ecx |
jnz .write_loop |
.ret: |
popad |
mov eax,ecx |
ret |
.page_not_found: |
call MEM_Heap_UnLock ;error has appeared in critical region |
sub ecx,[esp+24] ;[esp+24]<-->ecx |
neg ecx ;ecx=number_of_written_bytes |
mov [esp+28],ecx ;[esp+28]<-->eax |
popad |
ret |
;----------------------------------------------------------------------------- |
syscall_test: |
;for testing memory manager from applications. |
mov edx,ecx |
mov ecx,ebx |
call trans_address |
mov ebx,eax |
mov eax,[0x3000] |
call read_process_memory |
ret |
;----------------------------------------------------------------------------- |
read_process_memory: |
;Input: |
; eax - process slot |
; ebx - buffer address |
; ecx - buffer size |
; edx - start address in other process |
;Output: |
; eax - number of bytes read. |
pushad |
shl eax,8 |
mov eax,[0x80000+eax+0xB8] |
call MEM_Get_Linear_Address |
mov ebp,eax |
add edx,std_application_base_address |
.read_loop: |
;ebx = current buffer address |
;ecx>0 = current size |
;edx = current address in other process |
;ebp = linear address of page directory |
call MEM_Heap_Lock ;cli |
mov esi,edx |
shr esi,22 |
mov eax,[ebp+4*esi] ;find page directory entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address |
test eax,eax |
jz .page_not_found |
mov esi,edx |
shr esi,12 |
and esi,1023 |
mov eax,[eax+4*esi] ;find page table entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page |
test eax,eax |
jz .page_not_found |
mov esi,eax |
call MEM_Add_Reference_Linear;guarantee that page willn't disappear |
call MEM_Heap_UnLock ;sti |
mov edi,edx |
and edi,4095 |
add esi,edi ;add offset in page |
;esi = linear address corresponding edx in other process |
sub edi,4096 |
neg edi |
;edi=min(edi,ecx) - number of bytes to copy |
cmp edi,ecx |
jl .min_ecx |
mov edi,ecx |
.min_ecx: |
sub ecx,edi ;update size of remaining bytes |
add edx,edi ;update current pointer in other address space. |
push ecx |
mov ecx,edi ;ecx - number of bytes to read |
mov edi,ebx ;esi - source, edi - destination |
push esi |
;move ecx bytes |
test ecx,3 |
jnz .not_aligned |
shr ecx,2 |
rep movsd |
jmp .next_iter |
.not_aligned: |
rep movsb |
.next_iter: |
pop eax |
and eax,not (4096-1) ;eax - linear address of current page |
call MEM_Free_Page_Linear ;free reference |
mov ebx,edi ;new pointer to buffer - movsb automaticaly advance it. |
pop ecx ;restore number of remaining bytes |
test ecx,ecx |
jnz .read_loop |
popad |
mov eax,ecx |
ret |
.page_not_found: |
call MEM_Heap_UnLock ;error has appeared in critical region |
sub ecx,[esp+24] ;[esp+24]<-->ecx |
neg ecx ;ecx=number_of_read_bytes |
mov [esp+28],ecx ;[esp+28]<-->eax |
popad |
ret |
;----------------------------------------------------------------------------- |
check_region: |
;input: |
; ebx - start of buffer |
; ecx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
mov eax,[0x3000] |
jmp check_process_region |
;----------------------------------------------------------------------------- |
check_process_region: |
;input: |
; eax - slot |
; ebx - start of buffer |
; ecx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
test ecx,ecx |
jle .ok |
shl eax,5 |
cmp word [0x3000+eax+0xa],0 |
jnz .failed |
shl eax,3 |
mov eax,[0x80000+eax+0xb8] |
test eax,eax |
jz .failed |
call MEM_Get_Linear_Address |
push ebx |
push ecx |
push edx |
mov edx,ebx |
and edx,not (4096-1) |
sub ebx,edx |
add ecx,ebx |
mov ebx,edx |
add ecx,(4096-1) |
and ecx,not (4096-1) |
.loop: |
;eax - linear address of page directory |
;ebx - current page |
;ecx - current size |
mov edx,ebx |
shr edx,22 |
mov edx,[eax+4*edx] |
and edx,not (4096-1) |
test edx,edx |
jz .failed1 |
push eax |
mov eax,edx |
call MEM_Get_Linear_Address |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) |
mov eax,[eax+4*edx] |
and eax,not (4096-1) |
test eax,eax |
pop eax |
jz .failed1 |
add ebx,4096 |
sub ecx,4096 |
jg .loop |
pop edx |
pop ecx |
pop ebx |
.ok: |
mov eax,1 |
ret |
.failed1: |
pop edx |
pop ecx |
pop ebx |
.failed: |
xor eax,eax |
ret |
;----------------------------------------------------------------------------- |
new_sys_ipc: |
;input: |
; eax=1 - set ipc buffer area |
; ebx=address of buffer |
; ecx=size of buffer |
; eax=2 - send message |
; ebx=PID |
; ecx=address of message |
; edx=size of message |
cmp eax,1 |
jnz .no_ipc_def |
;set ipc buffer area |
mov edi,[0x3000] |
shl edi,8 |
add edi,0x80000 |
cli |
mov [edi+0xA0],ebx ;set fields in extended information area |
mov [edi+0xA4],ecx |
sti |
mov [esp+36],dword 0 ;success |
ret |
.no_ipc_def: |
cmp eax,2 |
jnz .no_ipc_send |
;send message |
cli |
;obtain slot from PID |
mov eax,ebx |
call pid_to_slot |
test eax,eax |
jz .no_pid |
mov ebp,eax |
;ebp = slot of other process |
shl eax,8 |
mov edi,[eax+0x80000+0xa0] ;is ipc area defined? |
test edi,edi |
jz .no_ipc_area |
mov esi,[eax+0x80000+0xa4] ;esi - size of buffer |
push dword -1 ;temp variable for read_process_memory |
mov ebx,esp |
push ecx |
push edx |
mov ecx,4 ;read 4 bytes |
mov eax,ebp |
mov edx,edi ;from beginning of buffer. |
call read_process_memory |
mov eax,[esp+8] |
test eax,eax |
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now |
add edx,4 ;move to next 4 bytes |
mov eax,ebp |
call read_process_memory ;read size of occupied space in buffer |
sub esi,8 |
sub esi,[esp] |
sub esi,[esp+8] ;esi=(buffer size)-(occupied size)-(message size)-(header of message size) |
js .buffer_overflow ;esi<0 - not enough memory in buffer |
mov esi,[esp+8] ;previous offset |
add dword [esp+8],8 |
mov edi,[esp] |
add [esp+8],edi ;add (size of message)+(size of header of message) to [buffer+4] |
mov eax,ebp |
call write_process_memory |
add edx,esi |
sub edx,4 ;move to beginning of place for our message |
mov eax,[second_base_address+0x3010] |
mov eax,[eax+0x4] ;eax - our PID |
mov [esp+8],eax |
mov eax,ebp |
call write_process_memory ;write PID |
mov ebx,esp ;address of size of message |
mov eax,ebp |
add edx,4 |
call write_process_memory ;write size of message |
add edx,4 |
pop ecx ;ecx - size of message |
pop eax |
call trans_address |
mov ebx,eax ;ebx - linear address of message |
add esp,4 ;pop temporary variable |
mov eax,ebp |
call write_process_memory ;write message |
sti |
;awake other process |
shl ebp,8 |
mov eax,ebp |
or [eax+0x800A8],dword 0x40 |
cmp dword [check_idle_semaphore],20 |
jge .ipc_no_cis |
mov dword [check_idle_semaphore],5 |
.ipc_no_cis: |
mov dword [esp+36],0 |
ret |
.no_ipc_send: |
mov dword [esp+36],-1 |
ret |
.no_pid: |
sti |
mov dword [esp+36],4 |
ret |
.no_ipc_area: |
sti |
mov dword [esp+36],1 |
ret |
.ipc_blocked: |
sti |
add esp,12 |
mov dword [esp+36],2 |
ret |
.buffer_overflow: |
sti |
add esp,12 |
mov dword [esp+36],3 |
ret |
;----------------------------------------------------------------------------- |
trans_address: |
;Input |
; eax - application address |
;Output |
; eax - linear address for kernel |
add eax,std_application_base_address |
ret |
;----------------------------------------------------------------------------- |
new_start_application_hd: |
;eax - file name (kernel address) |
;ebx - file name length |
;ecx - work area (kernel address) |
;ebp - parameters |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write message to message board |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
push ebp |
push ebx |
push eax |
push ecx |
call find_new_process_place ;find new process slot |
sti |
test eax,eax |
jz .failed |
;write application name |
mov eax,[esp+4] |
.find_last_byte: |
cmp byte [eax],0 |
jz .find_last_byte_end |
inc eax |
jmp .find_last_byte |
.find_last_byte_end: |
lea esi,[eax-11] ;last 11 bytes = application name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
cld |
rep movsb ;copy name to extended information about process |
;read header |
mov eax,[esp+4] ;file name |
mov esi,[esp] ;work area |
mov ecx,1 ;read from first block |
mov edx,1 ;read 1 block |
call read_hd_file |
test eax,eax |
jnz .cleanfailed |
mov esi,[esp] |
;check menuet signature |
cmp [esi+1024+0],dword 'MENU' ;read_hd_file function write file to +1024 offset |
jnz .cleanfailed |
cmp [esi+1024+4],word 'ET' |
jnz .cleanfailed |
add esi,1024 |
mov edi,0x90000 |
mov ecx,512/4 |
cld |
rep movsd ;copy first block to 0x90000 address for get_app_params function |
call get_app_params |
test esi,esi |
jz .cleanfailed |
mov eax,[new_process_place] |
call create_app_cr3_table ;create page directory |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4096-1 |
shr ecx,12 |
mov edx,eax ;edx - linear address of page directory |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
jz .cleanfailed_mem |
add edx,(std_application_base_address shr 20) |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
push edx ;save pointer to first page table |
mov edx,eax |
;read file |
mov ecx,1 |
xor ebp,ebp |
.loop1: |
;[esp] - pointer to current page directory entry |
;edx - pointer to current page table |
;ebp - offset in page |
;ecx - current cluster |
push edx |
mov eax,[esp+12] ;file name |
mov ebx,[esp+16] ;file name length |
mov esi,[esp+8] ;work area |
mov edx,1 ;number of blocks to read |
push ecx |
push ebp |
cli |
call read_hd_file |
sti |
pop ebp |
test eax,eax |
jnz .endloop1 ;check io errors |
mov esi,[esp+8+4] ;work area |
add esi,1024 |
mov eax,[esp+4] ;current page table |
mov eax,[eax] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address;calculate linear page address |
lea edi,[eax+ebp] ;add page offset |
mov ecx,512/4 |
cld |
rep movsd ;copy data |
pop ecx |
inc ecx ;next block |
mov eax,[app_i_end] ;todo: precalculate ([app_i_end]+4095)/4096 |
add eax,512-1 |
shr eax,9 ;calculate application image size |
cmp ecx,eax |
jg .endloop11 |
pop edx |
add ebp,512 ;new offset |
test ebp,4096 |
jz .loop1 |
xor ebp,ebp |
add edx,4 ;go to next page |
test edx,(4096-1) |
jnz .loop1 |
add dword [esp],4 ;go to next directory entry |
mov eax,[esp] |
mov eax,[eax] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax |
jmp .loop1 |
.endloop1: |
add esp,4 ;pop ecx |
.endloop11: |
add esp,4+4 ;pop edx, pop edx |
;add_app_parameters |
add esp,12 ;now pointer to parameters is on the top of the stack |
call new_start_application_fl.add_app_parameters ;start process |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem: |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
.failed: |
add esp,16 |
popad |
mov eax,-1 |
mov [application_table_status],0 |
sti |
ret |
end if |
/kernel/trunk/core/physmem.inc |
---|
0,0 → 1,218 |
virtual at 0 |
physical_mem_block: |
.start rd 1 |
.size rd 1 |
.flags rd 1 ;0-free, pid-used. |
.sizeof: |
end virtual |
max_physical_mem_blocks = 24 |
uglobal |
num_physical_mem_blocks rd 1 |
physical_mem_blocks rd 3*max_physical_mem_blocks |
endg |
Init_Physical_Memory_Manager: |
pushad |
mov edi,physical_mem_blocks |
mov ecx,3*max_physical_mem_blocks |
xor eax,eax |
cld |
rep stosd |
mov dword [num_physical_mem_blocks],2 |
mov [physical_mem_blocks+physical_mem_block.start],0x60000 |
mov [physical_mem_blocks+physical_mem_block.size],0x20000 ;128Kb |
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.start],0x780000 |
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.size],0x80000 ;512Kb |
popad |
ret |
Insert_Block: |
;input: |
; eax - handle |
;output: |
; none |
push eax ecx esi edi |
sub eax,[num_physical_mem_blocks] |
neg eax |
mov edi,physical_mem_block.sizeof |
imul eax,edi |
shr eax,2 |
mov ecx,eax |
mov esi,[num_physical_mem_blocks] |
imul esi,edi |
add esi,physical_mem_blocks |
lea edi,[esi+physical_mem_block.sizeof] |
std |
rep movsd |
pop edi esi ecx eax |
ret |
Delete_Block: |
;input: |
; eax - handle |
;output: |
; none |
pushad |
mov edi,eax |
sub eax,[num_physical_mem_blocks] |
neg eax |
dec eax |
mov esi,physical_mem_block.sizeof |
imul eax,esi |
imul edi,esi |
add edi,physical_mem_blocks |
lea esi,[edi+physical_mem_block.sizeof] |
mov ecx,eax |
shr ecx,2 |
cld |
rep movsd |
popad |
ret |
Allocate_Physical_Block: |
;input: |
; eax - size |
;output: |
; eax - address or 0 if not enough memory. |
pushad |
cmp [num_physical_mem_blocks],max_physical_mem_blocks |
jge .error |
mov ebx,eax |
xor eax,eax |
mov esi,physical_mem_blocks |
.loop: |
cmp dword [esi+physical_mem_block.flags],0 |
jnz .next |
cmp [esi+physical_mem_block.size],ebx |
jg .addblock |
jz .noaddblock |
.next: |
inc eax |
add esi,physical_mem_block.sizeof |
cmp eax,[num_physical_mem_blocks] |
jl .loop |
.error: |
popad |
xor eax,eax |
ret |
.noaddblock: |
mov eax,[esi+physical_mem_block.start] |
mov [esp+28],eax |
mov eax,[0x3010] |
mov eax,[eax+0x4] |
mov [esi+physical_mem_block.flags],eax |
popad |
ret |
.addblock: |
call Insert_Block |
inc dword [num_physical_mem_blocks] |
mov eax,[esi+physical_mem_block.start] |
mov [esp+28],eax |
mov ecx,[0x3010] |
mov ecx,[ecx+0x4] |
mov [esi+physical_mem_block.flags],ecx |
mov ecx,[esi+physical_mem_block.size] |
mov [esi+physical_mem_block.size],ebx |
sub ecx,ebx |
mov [esi+physical_mem_block.sizeof+physical_mem_block.size],ecx |
add ebx,[esi+physical_mem_block.start] |
mov [esi+physical_mem_block.sizeof+physical_mem_block.start],ebx |
mov dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 |
popad |
ret |
Free_Physical_Block: |
;input: |
; eax - address |
;output: |
; none |
pushad |
test eax,eax |
jz .ret |
mov ebx,eax |
xor eax,eax |
mov esi,physical_mem_blocks |
.loop: |
cmp ebx,[esi+physical_mem_block.start] |
jz .endloop |
inc eax |
add esi,physical_mem_block.sizeof |
cmp eax,[num_physical_mem_blocks] |
jl .loop |
jmp .ret |
.endloop: |
mov dword [esi+physical_mem_block.flags],0 |
test eax,eax |
jz .no_union_previous |
cmp dword [esi-physical_mem_block.sizeof+physical_mem_block.flags],0 |
jnz .no_union_previous |
mov ebx,[esi-physical_mem_block.sizeof+physical_mem_block.start] |
add ebx,[esi-physical_mem_block.sizeof+physical_mem_block.size] |
cmp ebx,[esi+physical_mem_block.start] |
jnz .no_union_previous |
mov ebx,[esi+physical_mem_block.size] |
add [esi-physical_mem_block.sizeof+physical_mem_block.size],ebx |
call Delete_Block |
dec eax |
dec [num_physical_mem_blocks] |
.no_union_previous: |
inc eax |
cmp eax,[num_physical_mem_blocks] |
jge .no_union_next |
cmp dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 |
jnz .no_union_next |
mov ebx,[esi+physical_mem_block.start] |
add ebx,[esi+physical_mem_block.size] |
cmp ebx,[esi+physical_mem_block.sizeof+physical_mem_block.start] |
jnz .no_union_next |
mov ebx,[esi+physical_mem_block.sizeof+physical_mem_block.size] |
add [esi+physical_mem_block.size],ebx |
call Delete_Block |
dec [num_physical_mem_blocks] |
.no_union_next: |
.ret: |
popad |
ret |
sys_allocate_physical_block: |
;eax - subfunction number |
mov eax,ebx |
call Allocate_Physical_Block |
mov [esp+36],eax |
ret |
sys_free_physical_block: |
;eax - subfunction number |
mov eax,ebx |
call Free_Physical_Block |
ret |
sys_set_buffer: |
add ecx,std_application_base_address |
isys_set_buffer: ;for using in kernel |
;eax - subfunction number |
;ebx - physical address |
;ecx - buffer start |
;edx - buffer size |
lea edi,[ebx+second_base_address] |
mov esi,ecx |
mov ecx,edx |
rep movsb |
ret |
sys_get_buffer: |
add ecx,std_application_base_address |
isys_get_buffer: ;for using in kernel |
;eax - subfunction number |
;ebx - physical address |
;ecx - buffer start |
;edx - buffer size |
mov edi,ecx |
lea esi,[ebx+second_base_address] |
mov ecx,edx |
rep movsb |
ret |
sys_internal_services: |
cmp eax,4 |
jle sys_sheduler |
cmp eax,5 |
jz sys_allocate_physical_block |
cmp eax,6 |
jz sys_free_physical_block |
cmp eax,7 |
jz sys_set_buffer |
cmp eax,8 |
jz sys_get_buffer |
ret |
/kernel/trunk/core/sched.inc |
---|
0,0 → 1,286 |
label next_usage_update dword at 0xB008 |
label timer_ticks dword at 0xFDF0 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
irq0: |
cmp [error_interrupt],-1 |
je no_error_in_previous_process |
mov edi,[error_interrupt] |
shl edi, 3 |
mov [edi+tss0i_l +5], word 01010000b *256 +11101001b |
mov edi,[error_interrupt] |
shl edi,7 |
add edi,0x290000 |
mov esi,[error_interrupt_entry] |
mov [edi+l.eip-tss_sceleton],esi |
mov [edi+l.eflags-tss_sceleton],dword 0x11002 |
mov [0xffff],byte 0 |
mov [error_interrupt],-1 |
no_error_in_previous_process: |
mov edi,[0x3000] |
shl edi, 3 |
; fields of TSS descriptor: |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
inc dword [timer_ticks] |
mov eax, [timer_ticks] |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
call playNote ; <<<--- INSERT THIS LINE !!!!!!!!!! |
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
cmp eax,[next_usage_update] |
jb .nocounter |
add eax,100 |
mov [next_usage_update],eax |
call updatecputimes |
.nocounter: |
mov edi, [0x3010] |
mov ebx, [edi+0x18] ; time stamp counter add |
call _rdtsc |
sub eax, ebx |
add eax, [edi+0x14] ; counter sum |
mov [edi+0x14], eax |
mov ebx,[0x3000] |
cmp [0xffff], byte 1 ;1 |
je do_not_change_task ;je |
.waiting_for_termination: |
.waiting_for_reuse: |
.waiting_on_queue: |
add edi,0x20 |
inc ebx |
mov al, byte [edi+0xA] |
cmp al, 3 |
je .waiting_for_termination |
cmp al, 4 |
je .waiting_for_termination |
cmp al, 9 |
je .waiting_for_reuse |
cmp al, 16 |
je .waiting_on_queue |
cmp al, 17 |
je .waiting_on_queue |
cmp ebx,[0x3004] |
jbe nsched0 |
mov ebx,1 |
mov edi,0x3020 |
nsched0: |
mov [0x3000],ebx |
mov [0x3010],edi |
do_not_change_task: |
mov edx,[0x3000] |
lea edx,[tss0sys+8*edx] |
;mov [8*0x40+idts+8+0], word 0 |
mov [8*0x40+idts+8+2],dx |
;mov [8*0x40+idts+8+4],word 11100101b*256 |
;mov [8*0x40+idts+8+6], word 0 |
call _rdtsc |
mov [edi+0x18],eax |
cmp [0xffff],byte 0 |
je nodecffff |
dec byte [0xffff] |
nodecffff: |
shl ebx, 3 |
xor eax, eax |
add ebx, tss0 |
mov word [0xB004], bx ; selector ;mov [tss_s],bx |
mov dword [0xB000], eax ; offset |
mov al,0x20 ; send End Of Interrupt signal |
mov dx,0x20 |
out dx,al |
.switch: |
jmp pword [0xB000] |
inc [context_counter] ;noname & halyavin |
jmp irq0 |
iglobal |
context_counter dd 0 ;noname & halyavin |
endg |
align 4 |
change_task: |
mov [0xffff],byte 2 |
dec dword [timer_ticks] ; because irq0 will increase it |
int 0x20 ; irq0 handler |
ret |
align 4 |
updatecputimes: |
mov eax,[idleuse] |
mov [idleusesec],eax |
mov [idleuse],dword 0 |
mov ecx, [0x3004] |
mov edi, 0x3020 |
.newupdate: |
mov ebx,[edi+0x14] |
mov [edi+0x1c],ebx |
mov [edi+0x14],dword 0 |
add edi,0x20 |
dec ecx |
jnz .newupdate |
ret |
; |
; Wait queue is 16 bytes |
; dd return code +12 |
; dd pointer to process +8 |
; dd prev +4 |
; dd next +0 |
; |
; eax - pointer to pointer to the wait queue |
; return: |
; ecx - return code |
sleep_on_queue: |
sub esp,16 ; reserve space for wait node |
mov ecx,esp ; ecx=this_node, [eax]=queue |
pusha |
mov ebx,[0x3010] ; get pointer to the current process |
mov [ecx+8],ebx |
pushf |
cli ; adding element to the wait queue must be atomic |
mov edi,[eax] ; edi=queue |
and edi,edi ; check if queue is empty |
jz .is_empty |
; add element at the end of wait queue |
mov edx,[edi+4] ; get pointer to prev edx=queue->prev |
mov [ecx+4],edx ; this_node->prev=queue->prev |
mov [ecx+0],edi ; this_node->next=queue |
mov [edx+0],ecx ; this_node->prev->next=this_node |
mov [edi+4],ecx ; queue->prev=this_node |
jmp .added_ok |
.is_empty: |
; set this element as first in the queue |
mov [ecx+0],ecx ; this_node->next=this_node |
mov [ecx+4],ecx ; this_node->prev=this_node |
mov [eax],ecx ; [queue]=this_node |
.added_ok: |
popf ; we can safely restore interrupts |
mov [ebx+0xa],byte 17 ; set current task state as sleeping |
call change_task ; schedule new thread |
; someone has called wake_up_queue |
pushf ; disable interrupts |
cli |
mov edx,[ecx+0] ; edx=this_node->next |
mov esi,[ecx+4] ; esi=this_node->prev |
; check if we need to remove this node from head |
cmp [eax],ecx |
jne .no_head |
cmp [ecx+0],ecx ; check if queue is empty |
jne .not_empty |
mov [eax],dword 0 |
jmp .no_head |
.not_empty: |
mov [eax],edx |
; remove our node from the queue (this must be atomic) |
.no_head: |
mov [edx+4],esi ; this_node->next->prev=this_node->prev |
mov [esi+0],edx ; this_node->prev->next=this_node->next |
popf |
popa |
add esp,12 |
pop ecx |
ret |
; eax - pointer to the wait queue |
; ebx - wake up all (1=yes, 0=no) |
; ecx - return code |
; return: |
; ebx - number of processes woken |
wake_up_queue: |
and eax,eax |
jnz .nz |
ret |
.nz: |
push eax |
push ebx |
push ecx |
push edx |
push esi |
pushf |
cli |
xor ebx,ebx |
mov edx,eax |
.wake_loop: |
mov [edx+12],ecx |
mov esi,[edx+8] |
mov byte [esi+0xa],0 |
inc ebx |
mov edx,[edx+0] |
cmp edx,eax |
jne .wake_loop |
and ebx,ebx |
jz .wake_up_1 |
.return_it: |
popf |
pop esi |
pop edx |
pop ecx |
add esp,4 |
pop eax |
ret |
.wake_up_1: |
mov [eax+12],ecx |
mov ecx,[eax+8] |
mov byte [ecx+0xa],0 |
jmp .return_it |
/kernel/trunk/core/sync.inc |
---|
0,0 → 1,111 |
if ~defined sync_inc |
sync_inc_fix: |
sync_inc fix sync_inc_fix |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;Synhronization for MenuetOS. ;; |
;;Author: Halyavin Andrey, halyavin@land.ru ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;simplest mutex. |
macro SimpleMutex name |
{ |
; iglobal |
name dd 0 |
name#.type = 1 |
; endg |
} |
macro WaitSimpleMutex name |
{ |
local start_wait,ok |
start_wait=$ |
cli |
cmp [name],dword 0 |
jz ok |
sti |
call change_task |
jmp start_wait |
ok=$ |
push eax |
mov eax,dword [0x3010+second_base_address] |
mov eax,[eax+0x4] |
mov [name],eax |
pop eax |
sti |
} |
macro ReleaseSimpleMutex name |
{ |
mov [name],dword 0 |
} |
macro TryWaitSimpleMutex name ;result in eax and in flags |
{ |
local ok,try_end |
cmp [name],dword 0 |
jz ok |
xor eax,eax |
jmp try_end |
ok=$ |
xor eax,eax |
inc eax |
try_end=$ |
} |
macro SimpleCriticalSection name |
{ |
; iglobal |
name dd 0 |
dd 0 |
name#.type=2 |
; endg |
} |
macro WaitSimpleCriticalSection name |
{ |
local start_wait,first_wait,inc_counter,end_wait |
push eax |
mov eax,[0x3010+second_base_address] |
mov eax,[eax+0x4] |
start_wait=$ |
cli |
cmp [name],dword 0 |
jz first_wait |
cmp [name],eax |
jz inc_counter |
sti |
call change_task |
jmp start_wait |
first_wait=$ |
mov [name],eax |
mov [name+4],dword 1 |
jmp end_wait |
inc_counter=$ |
inc dword [name+4] |
end_wait=$ |
sti |
pop eax |
} |
macro ReleaseSimpleCriticalSection name |
{ |
local release_end |
dec dword [name+4] |
jnz release_end |
mov [name],dword 0 |
release_end=$ |
} |
macro TryWaitSimpleCriticalSection name ;result in eax and in flags |
{ |
local ok,try_end |
mov eax,[0x3000+second_base_address] |
mov eax,[eax+0x4] |
cmp [name],eax |
jz ok |
cmp [name],0 |
jz ok |
xor eax,eax |
jmp try_end |
ok=$ |
xor eax,eax |
inc eax |
try_end=$ |
} |
_cli equ call MEM_HeapLock |
_sti equ call MEM_HeapUnLock |
end if |
/kernel/trunk/core/sys32.inc |
---|
0,0 → 1,2301 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; MenuetOS process management, protected ring3 ;; |
;; ;; |
;; Distributed under GPL. See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
; GDT TABLE |
gdts: |
dw gdte-$-1 |
dd gdts |
dw 0 |
int_code_l: |
os_code_l: |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10011010b |
db 0x00 |
int_data_l: |
os_data_l: |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10010010b |
db 0x00 |
graph_data_l: |
dw 0x3ff |
dw 0x0000 |
db 0x00 |
dw 11010000b *256 +11110010b |
db 0x00 |
tss0_l: |
times (max_processes+10) dd 0,0 |
tss0i_l: |
times 0x41 dq 0 ;(256+10) dd 0,0 |
app_code_l: |
times (max_processes+10) dd 0,0 |
app_data_l: |
times (max_processes+10) dd 0,0 |
tss0sys_l: |
times (max_processes+10) dd 0,0 |
gdte: |
; <IP 05.02.2005> |
idtreg: |
dw 8*0x41-1 |
dd idts+8 |
label idts at 0xB100-8 |
;idte = idts + 8 + 0x60 |
; </IP> ; old code below: |
;align 32 |
;idts: |
; dw idte-$-1 |
; dd idts+8 |
; dw 0 |
; times 0x62 dd 0,0 |
;idte: |
build_process_gdt_tss_pointer: |
mov ecx,tss_data |
mov edi,0 |
setgdtl2: |
mov [edi+gdts+ tss0 +0], word tss_step |
mov [edi+gdts+ tss0 +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0 +4], al |
mov [edi+gdts+ tss0 +7], ah |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
add ecx,tss_step |
add edi,8 |
cmp edi,8*(max_processes+5) |
jbe setgdtl2 |
ret |
;build_process_gdt_gate_pointer: |
; mov edi,0 |
; mov dx,tss0 |
; setidtl1: |
; mov ecx,[esi] |
; mov [edi+gdts+ tss0t +0], word 0 |
; mov [edi+gdts+ tss0t +2], dx |
; mov [edi+gdts+ tss0t +4], word 11100101b*256 |
; mov [edi+gdts+ tss0t +6], word 0 |
; add dx,8 |
; add edi,8 |
; cmp edi,8*(max_processes+5) |
; jb setidtl1 |
; ret |
build_interrupt_table: |
mov [l.eflags],dword 0x11002 |
mov [l.ss0], int_data |
;mov [l.ss1], ring1_data |
;mov [l.ss2], ring2_data |
mov [l.esp0], 0x52000 |
mov [l.esp1], 0x53000 |
mov [l.esp2], 0x54000 |
mov eax,cr3 |
mov [l.cr3],eax |
mov [l.cs],int_code |
mov [l.ss],int_data |
mov [l.ds],int_data |
mov [l.es],int_data |
mov [l.fs],int_data |
mov [l.gs],int_data |
mov eax,sys_int |
mov [l.esp],0x720000 |
mov edi,0x290000 |
newint: |
push edi |
mov ebx,[eax] |
mov [l.eip],ebx |
mov esi,tss_sceleton |
mov ecx,120/4 |
cld |
rep movsd |
pop edi |
add edi,128 |
add [l.esp],1024 |
add eax,4 |
cmp eax,sys_int+4*0x40 ;0x60 |
jbe newint ;jb |
;; |
mov esi,boot_sched_3_2 |
call boot_log |
mov ecx,0x290000 |
mov edi,0 |
setgdtl2i: |
mov [edi+gdts+ tss0i +0], word 128 |
mov [edi+gdts+ tss0i +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0i +4], al |
mov [edi+gdts+ tss0i +7], ah |
mov [edi+gdts+ tss0i +5], word 01010000b *256 +11101001b |
add ecx,128 |
add edi,8 |
cmp edi,8*0x40 ;0x60 |
jbe setgdtl2i |
;; |
mov esi,boot_sched_3_3 |
call boot_log |
mov edi,0 |
mov edx,tss0i |
setidtl2: |
mov [edi+idts+ 8 +0], word 0 |
mov [edi+idts+ 8 +2], dx |
mov [edi+idts+ 8 +4], word 10000101b*256 ; task gate DPL=0 |
; cmp edi,0x40*8 |
; jne no_sw_int |
; mov [edi+idts+ 8 +4], word 11100101b*256 ; task gate DPL=3 |
; no_sw_int: |
mov [edi+idts+ 8 +6], word 0 |
add edx,8 |
add edi,8 |
cmp edi,8*0x40 ;0x60 |
jbe setidtl2 ;jb |
; <Ivan Poddubny 06.02.2005> |
; THIS CODE WON'T WORK ;-( |
; because each process's 0-level stack points to the same area |
; and if task switch occurs and another process is being interrupted |
; a stack overflow happens |
; The only way to solve that problem is to disable interrupts |
; while 0x40-handler is working |
; Then we have to make all entries in the IDT INTERRUPT gates, not TASK |
; mov edi, idts+8 |
; mov esi, sys_int |
; mov ecx, 32 |
; @@: |
; mov eax, [esi] |
; mov [edi], ax ; lower part of offset |
; mov [edi+2], word os_code ; segment selector |
; shr eax, 16 |
; mov [edi+4], word 10001110b shl 8 ; interrupt descriptor |
; mov [edi+6], ax |
; add esi, 4 |
; add edi, 8 |
; dec ecx |
; jnz @b |
; </Ivan Poddubny> |
ret |
build_syscall_interrupt_table: |
mov [l.eflags],dword 0x11002 |
mov [l.ss0], int_data ;code |
;mov [l.ss1], ring1_data ;code |
;mov [l.ss2], ring2_data ;code |
mov [l.esp0], 0x52000 |
mov [l.esp1], 0x53000 |
mov [l.esp2], 0x54000 |
mov eax,cr3 |
mov [l.cr3],eax |
mov [l.cs],int_code |
mov [l.ss],int_data |
mov [l.ds],int_data |
mov [l.es],int_data |
mov [l.fs],int_data |
mov [l.gs],int_data |
mov [l.esp],sysint_stack_data |
mov edi,0x298000 |
newint2: |
push edi |
mov ebx,i40 |
mov [l.eip],ebx |
mov esi,tss_sceleton |
mov ecx,120/4 |
cld |
rep movsd |
pop edi |
add [l.esp],4096 |
add edi,128 |
;add eax,4 |
cmp edi,0x298000+128*(max_processes+5) |
jb newint2 |
;; |
mov ecx,0x298000 |
mov edi,0 |
setgdtl2i2: |
mov [edi+gdts+ tss0sys +0], word 128 |
mov [edi+gdts+ tss0sys +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0sys +4], al |
mov [edi+gdts+ tss0sys +7], ah |
mov [edi+gdts+ tss0sys +5], word 01010000b *256 +11101001b |
add ecx,128 |
add edi,8 |
cmp edi,8*(max_processes+5) |
jbe setgdtl2i2 |
;; |
;mov dx,tss0sys |
mov edi,8*0x40+idts+8 |
mov [edi + 0], word 0 |
mov [edi + 2], word tss0sys ;dx |
mov [edi + 4], word 11100101b*256 |
mov [edi + 6], word 0 |
mov edi,8*0x38+idts+8 |
mov eax, i38 |
mov [edi], ax ; lower part of offset |
mov [edi+2], word os_code ; segment selector |
shr eax, 16 |
mov [edi+4], word 11101110b shl 8 ; 32-bit interrupt gate, DPL 3 |
mov [edi+6], ax |
ret |
align 4 |
i38: |
; load data selectors |
pushfd |
push ds es |
push eax |
mov ax, os_data |
mov ds, ax |
mov es, ax |
pop eax |
pushad |
push edi |
mov edi, eax |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov esi, [esp] |
and edi, 0xFF |
call dword [servetable+edi*4] |
add esp, 4 |
popad |
pop es ds |
popfd |
iret |
iglobal |
sys_int: |
dd s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,sa,sb,sc,sd,se,sf |
dd s10 ,s11 ; ,i_unknown12,i_unknown13 |
; dd i_unknown14,i_unknown15,i_unknown16,i_unknown17 |
; dd i_unknown18,i_unknown19,i_unknown1a,i_unknown1b |
; dd i_unknown1c,i_unknown1d,i_unknown1e,i_unknown1f |
times 14 dd unknown_interrupt |
dd irq0 ,irq1 ,p_irq2 ,p_irq3 ,p_irq4 ,p_irq5,p_irq6 ,p_irq7 |
dd p_irq8,p_irq9,p_irq10,p_irq11,p_irq12,irqD ,p_irq14,p_irq15 |
;dd i_unknown30,i_unknown31,i_unknown32,i_unknown33 |
;dd i_unknown34,i_unknown35,i_unknown36,i_unknown37 |
;dd i_unknown38,i_unknown39,i_unknown3a,i_unknown3b |
;dd i_unknown3c,i_unknown3d,i_unknown3e,i_unknown3f |
times 16 dd unknown_interrupt |
dd i40 |
endg |
uglobal |
tss_sceleton: |
l.back dw 0,0 |
l.esp0 dd 0 |
l.ss0 dw 0,0 |
l.esp1 dd 0 |
l.ss1 dw 0,0 |
l.esp2 dd 0 |
l.ss2 dw 0,0 |
l.cr3 dd 0 |
l.eip dd 0 |
l.eflags dd 0 |
l.eax dd 0 |
l.ecx dd 0 |
l.edx dd 0 |
l.ebx dd 0 |
l.esp dd 0 |
l.ebp dd 0 |
l.esi dd 0 |
l.edi dd 0 |
l.es dw 0,0 |
l.cs dw 0,0 |
l.ss dw 0,0 |
l.ds dw 0,0 |
l.fs dw 0,0 |
l.gs dw 0,0 |
l.ldt dw 0,0 |
l.trap dw 0 |
l.io dw 0 |
endg |
s0: |
cli |
mov [error_interrupt],0x0 |
mov [error_interrupt_entry],dword s0 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s1: |
cli |
mov [error_interrupt],0x1 |
mov [error_interrupt_entry],dword s1 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s2: |
cli |
mov [error_interrupt],0x2 |
mov [error_interrupt_entry],dword s2 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s3: |
cli |
mov [error_interrupt],0x3 |
mov [error_interrupt_entry],dword s3 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s4: |
cli |
mov [error_interrupt],0x4 |
mov [error_interrupt_entry],dword s4 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s5: |
cli |
mov [error_interrupt],0x5 |
mov [error_interrupt_entry],dword s5 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s6: |
cli |
mov [error_interrupt],0x6 |
mov [error_interrupt_entry],dword s6 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
;;;;;;;;;;;;;;;;;;;;;;; |
;; FPU ERROR HANDLER ;; |
;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
s7: |
; <IP 05.02.2004> |
cli |
; </IP> |
mov edi, 7*8 |
mov [edi+gdts+ tss0i +5], word 01010000b *256 +11101001b |
mov edi,[0x3000] |
shl edi, 3 |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
; save a copy of current task's TSS to fpu_tss |
mov esi,[0x3000] |
imul esi,tss_step |
add esi,tss_data |
mov edi,fpu_tss |
mov ecx,120/4 |
cld |
rep movsd |
; get base address of our TSS and... |
mov esi,[0x3000] |
imul esi,tss_step |
add esi,tss_data |
; ...init segments, stack, eip, flags |
mov word [esi+l.cs-tss_sceleton],int_code |
mov word [esi+l.ss-tss_sceleton],int_data |
mov word [esi+l.ds-tss_sceleton],int_data |
mov word [esi+l.es-tss_sceleton],int_data |
mov word [esi+l.fs-tss_sceleton],int_data |
mov word [esi+l.gs-tss_sceleton],int_data |
mov dword [esi+l.esp-tss_sceleton],fpu_stack+4*8 |
mov dword [esi+l.eip-tss_sceleton],fpu_handler |
mov dword [esi+l.eflags-tss_sceleton],0x11002 |
; then execute this task |
mov ebx, [0x3000] |
shl ebx,3 |
add ebx, tss0 ;t |
mov [0xB004], bx |
jmp pword [0xB000] |
jmp s7 |
s8: |
cli |
mov [error_interrupt],0x8 |
mov [error_interrupt_entry],dword s8 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s9: |
cli |
mov [error_interrupt],0x9 |
mov [error_interrupt_entry],dword s9 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sa: |
cli |
mov [error_interrupt],0xa |
mov [error_interrupt_entry],dword sa |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sb: |
cli |
mov [error_interrupt],0xb |
mov [error_interrupt_entry],dword sb |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sc: |
cli |
mov [error_interrupt],0xc |
mov [error_interrupt_entry],dword sc |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sd: |
cli |
mov [error_interrupt],0xd |
mov [error_interrupt_entry],dword sd |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
se: |
cli |
mov [error_interrupt],0xe |
mov [error_interrupt_entry],dword se |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
sf: |
cli |
mov [error_interrupt],0xf |
mov [error_interrupt_entry],dword sf |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s10: |
cli |
mov [error_interrupt],0x10 |
mov [error_interrupt_entry],dword s10 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
s11: |
cli |
mov [error_interrupt],0x11 |
mov [error_interrupt_entry],dword s11 |
call show_error_parameters |
mov edx,[0x3010] |
mov [edx+0xa],byte 4 |
jmp change_task |
writehex: |
pusha |
mov ecx,eax |
mov ax,word [printerrorat] |
shl eax,16 |
mov ax,[esp+32+4] |
sub ax,60 |
mov edx,1 |
mov esi,8 |
mov ebx,0xffffff |
whl1: |
push ecx |
and ecx,0xf |
add ecx,hexletters |
mov edi,1 |
mov cl,[ecx] |
mov edi,[write_error_to] |
mov [edi],cl |
dec [write_error_to] |
pop ecx |
shr ecx,4 |
sub eax,6*65536 |
dec esi |
jnz whl1 |
popa |
ret |
iglobal |
hexletters db '0123456789ABCDEF' |
error_interrupt dd -1 |
error_interrupt_entry dd -1 |
printerrorat dd 300 |
process_error db 'K : Process - forced terminate INT: 00000000',13,10,0 |
process_pid db 'K : Process - forced terminate PID: 00000000',13,10,0 |
process_eip db 'K : Process - forced terminate EIP: 00000000',13,10,0 |
system_error db 'K : Kernel error',13,10,0 |
endg |
uglobal |
write_error_to dd 0x0 |
endg |
show_error_parameters: |
mov [write_error_to],process_pid+43 |
mov eax,[0x3000] |
shl eax, 5 |
mov eax,[0x3000+4+eax] |
call writehex |
mov [write_error_to],process_error+43 |
mov eax,[error_interrupt] |
call writehex |
mov eax,[0x3000] |
shl eax,8 |
cmp [0x80000+eax+0xB0],dword 0 |
jnz .system_error |
mov eax,[0x3000] |
imul eax,tss_step |
mov eax,[eax+tss_data+l.eip-tss_sceleton] |
.out_eip: |
mov [write_error_to],process_eip+43 |
call writehex |
mov esi,process_error |
call sys_msg_board_str |
mov esi,process_pid |
call sys_msg_board_str |
mov esi,process_eip |
call sys_msg_board_str |
ret |
.system_error: |
mov esi,system_error |
call sys_msg_board_str |
mov eax,[0x3000] |
shl eax,7 |
mov eax,[eax+0x298000+l.eip-tss_sceleton] |
jmp .out_eip |
irq5: |
call restore_caller |
mov dx,word [sb16] |
add dx,0xe |
in al,dx |
; mov byte [SB16_Status],0 |
mov [check_idle_semaphore],5 |
mov al,0x20 |
out 0x20,al |
call return_to_caller |
jmp irq5 |
irqD: |
call restore_caller |
mov dx,0xf0 |
mov al,0 |
out dx,al |
mov dx,0xa0 |
mov al,0x20 |
out dx,al |
mov dx,0x20 |
out dx,al |
mov ds,cx |
mov es,cx |
mov fs,cx |
call return_to_caller |
jmp irqD |
p_irq2: |
call restore_caller |
mov edi,2 ; 1 |
call irqhandler ; 2/5 |
call return_to_caller |
jmp p_irq2 |
p_irq3: |
call restore_caller |
mov edi,3 |
call irqhandler |
call return_to_caller |
jmp p_irq3 |
p_irq4: |
call restore_caller |
mov edi,4 |
call irqhandler |
call return_to_caller |
jmp p_irq4 |
p_irq5: |
call restore_caller |
mov edi,5 |
call irqhandler |
call return_to_caller |
jmp p_irq5 |
p_irq6: |
call restore_caller |
call fdc_irq |
mov edi,6 |
call irqhandler |
call return_to_caller |
jmp p_irq6 |
p_irq7: |
call restore_caller |
mov edi,7 |
call irqhandler |
call return_to_caller |
jmp p_irq7 |
p_irq8: |
call restore_caller |
mov edi,8 |
call irqhandler |
call return_to_caller |
jmp p_irq8 |
p_irq9: |
call restore_caller |
mov edi,9 |
call irqhandler |
call return_to_caller |
jmp p_irq9 |
p_irq10: |
call restore_caller |
mov edi,10 |
call irqhandler |
call return_to_caller |
jmp p_irq10 |
p_irq11: |
call restore_caller |
mov edi,11 |
call irqhandler |
call return_to_caller |
jmp p_irq11 |
p_irq12: |
call restore_caller |
mov edi,12 |
call irqhandler |
call return_to_caller |
jmp p_irq12 |
p_irq13: |
call restore_caller |
mov edi,13 |
call irqhandler |
call return_to_caller |
jmp p_irq13 |
p_irq14: |
call restore_caller |
mov edi,14 |
call irqhandler |
call return_to_caller |
jmp p_irq14 |
p_irq15: |
call restore_caller |
mov edi,15 |
call irqhandler |
call return_to_caller |
jmp p_irq15 |
align 4 |
restore_caller: |
mov edi,[0x3000] |
shl edi, 3 |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
ret |
align 4 |
return_to_caller: |
mov ebx,[0x3000] |
shl bx,3 |
add bx,tss0;t |
mov [tss_irq12],bx |
db 0xea |
dd 0 |
tss_irq12 dw tss0;t |
ret |
uglobal |
irqh dd 0x0 |
endg |
irqhandler: |
push edi |
mov esi,edi ; 1 |
shl esi,6 ; 1 |
add esi,irq00read ; 1 |
shl edi,12 ; 1 |
add edi,0x2E0000 |
mov [check_idle_semaphore],5 |
irqnewread: |
mov dx,[esi] ; 2+ |
cmp dx,0 ; 1 |
jz irqover |
cmp [esi+3],byte 1 ; 2 ; byte read |
jne noirqbyte ; 4-11 |
in al,dx |
mov edx,[edi] |
cmp edx,4000 |
je irqfull |
mov ebx,edi |
add ebx,0x10 |
add ebx,edx |
mov [ebx],al |
inc edx |
mov [edi],edx |
add esi,4 |
jmp irqnewread |
noirqbyte: |
cmp [esi+3],byte 2 ; word read |
jne noirqword |
in ax,dx |
mov edx,[edi] |
cmp edx,4000 |
je irqfull |
mov ebx,edi |
add ebx,0x10 |
add ebx,edx |
mov [ebx],ax |
add edx,2 |
mov [edi],edx |
add esi,4 |
jmp irqnewread |
noirqword: |
irqfull: |
irqover: |
mov al,0x20 ; ready for next irq |
out 0x20,al |
pop ebx |
cmp ebx,7 |
jbe noa0 |
out 0xa0,al |
noa0: |
ret |
; this code should never get control! |
; applications can use only 0x40 interrupt |
unknown_interrupt: |
@@: call change_task |
jmp @b |
compare_to_thread: |
push ebx |
mov eax,edx |
shl eax, 3 |
add eax,gdts+ app_code-3 |
mov ebx,[eax] |
cmp ebx,[old_code_0] |
jne ctt0 |
mov ebx,[eax+4] |
cmp ebx,[old_code_1] |
jne ctt0 |
pop ebx |
mov eax,1 |
ret |
ctt0: |
pop ebx |
mov eax,0 |
ret |
check_for_thread_mem: |
pusha |
mov ecx,[0x3004] |
cftm0: |
mov eax,ecx |
shl eax, 8 |
add eax,gdts+ app_code-3 |
mov ebx,[eax] |
cmp ebx,[old_code_0] |
jne cftm1 |
mov ebx,[eax+4] |
cmp ebx,[old_code_1] |
jne cftm1 |
mov eax,ecx ; new code segments |
shl eax, 3 ;imul eax,8 |
add eax,gdts+ app_code-3 |
mov ebx,[new_code_0] |
mov [eax],ebx |
mov ebx,[new_code_1] |
mov [eax+4],ebx |
mov eax,ecx ; new data segments |
shl eax, 3 |
add eax,gdts+ app_data-3 |
mov ebx,[new_data_0] |
mov [eax],ebx |
mov ebx,[new_data_1] |
mov [eax+4],ebx |
cmp [new_pos],0 ; new memory position segments |
je no_new_postition_for_thread |
mov eax,ecx |
shl eax, 5 |
add eax,0x3000 |
mov ebx,[new_pos] |
mov [eax+0x10],ebx |
no_new_postition_for_thread: |
mov eax,ecx ; new amount of memory |
shl eax, 8 |
add eax,0x80000 |
mov ebx,[new_amount] |
mov [eax+0x8C],ebx |
cftm1: |
dec ecx |
jnz cftm0 |
popa |
ret |
save_for_thread_check: |
; save for thread check |
pusha |
mov esi,[0x3000] |
;imul esi,8 |
shl esi, 3 |
add esi,gdts+ app_code-3 +0 |
mov edi,old_code_0 |
mov ecx,8 |
cld |
rep movsb |
popa |
ret |
save_new_position_for_threads: |
; new code segment for thread check |
pusha |
mov esi,[0x3000] |
;imul esi,8 |
shl esi, 3 |
add esi,gdts+ app_code-3 +0 |
mov edi,new_code_0 |
mov ecx,8 |
cld |
rep movsb |
popa |
; new data segment for thread check |
pusha |
mov esi,[0x3000] |
;imul esi,8 |
shl esi, 3 |
add esi,gdts+ app_data-3 +0 |
mov edi,new_data_0 |
mov ecx,8 |
cld |
rep movsb |
popa |
ret |
set_application_table_status: |
push eax |
mov eax,[0x3000] |
;imul eax,32 |
shl eax, 5 |
add eax,0x3000+4 |
mov eax,[eax] |
mov [application_table_status],eax |
pop eax |
ret |
clear_application_table_status: |
push eax |
mov eax,[0x3000] |
;imul eax,32 |
shl eax, 5 |
add eax,0x3000+4 |
mov eax,[eax] |
cmp eax,[application_table_status] |
jne apptsl1 |
mov [application_table_status],0 |
apptsl1: |
pop eax |
ret |
uglobal |
old_code_0 dd 0x0 |
old_code_1 dd 0x0 |
; |
new_code_0 dd 0x0 |
new_code_1 dd 0x0 |
new_data_0 dd 0x0 |
new_data_1 dd 0x0 |
new_pos dd 0x0 |
new_amount dd 0x0 |
endg |
sys_resize_app_memory: |
; eax = 1 - resize |
; ebx = new amount of memory |
cmp eax,1 |
jne no_application_mem_resize |
mov eax,[0x3010] |
cmp dword [eax+0x10],std_application_base_address |
jz new_mem_resize ;resize for new type of processes |
add ebx,4095 |
shr ebx,12 |
shl ebx,12 |
mov ebp,ebx |
; wait for process table to be free |
rsm0: |
cli |
cmp [application_table_status],0 |
je rsm1 |
sti |
call change_task |
jmp rsm0 |
rsm1: |
call set_application_table_status |
sti |
cmp ebx,0 ; other than zero |
je mem_resize_unsuccess |
call save_for_thread_check |
; find a free place |
mov esi,[0xfe84] ; application memory start |
mov edi,ebp |
add edi,esi |
dec edi |
rfgdt: |
mov edx,2 |
rfindgdtl1: |
call compare_to_thread |
cmp eax,1 |
je rfindfl3 |
mov ecx,edx |
shl ecx,3 |
; eax run base -> ebx limit |
mov al,[ecx+gdts+ app_code-3 +4] |
mov ah,[ecx+gdts+ app_code-3 +7] |
shl eax,16 |
mov ax,[ecx+gdts+ app_code-3 +2] |
;!!mem |
cmp eax,std_application_base_address |
jz rfindfl3 |
;!!mem |
movzx ebx,word [ecx+gdts+ app_code-3 +0] |
shl ebx,12 |
add ebx,eax |
cmp eax,edi |
jg rfindfl3 |
cmp ebx,esi |
jb rfindfl3 |
add esi,4096 |
add edi,4096 |
cmp edi,[0xfe8c] ; < c_memory |
jbe rfgdt |
jmp rfind_free_ret_2 ;; not enough memory |
rfindfl3: |
inc edx |
cmp edx,[0x3004] |
jbe rfindgdtl1 |
rfindfl1: |
rthread_c: |
mov ecx,[0x3000] |
shl ecx,3 |
inc edi |
sub edi,esi |
add edi,4095 |
shr edi,12 |
dec edi |
; code |
mov eax,esi |
mov ebx,edi |
mov [ecx+gdts+ app_code-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_code-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_code-3 +7], ah ; base 31:24 |
mov [ecx+gdts+ app_code-3 +0], bx ; limit |
; data |
mov eax,esi |
mov [ecx+gdts+ app_data-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_data-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_data-3 +7], ah ; base 31:24 |
movzx edx,word [ecx+gdts+ app_code-3 +0] ; save limit |
mov [ecx+gdts+ app_data-3 +0], bx ; limit |
and ebx,0xffff |
cmp ebx,edx ; copy smaller from memory sizes |
jge noedxebxxchg |
mov edx,ebx |
noedxebxxchg: |
movzx ecx,dx |
shl ecx,12 |
add ecx,4096 |
mov edi,esi |
mov eax,[0x3010] |
mov esi,[eax+0x10] |
mov [eax+0x10],edi ; new memory position |
mov eax,[0x3000] ; new memory size |
shl eax,8 |
add eax,0x80000 |
mov [eax+0x8c],ebp |
mov [new_pos],edi ; new position for threads |
mov [new_amount],ebp ; new amount of mem for threads |
cmp esi,edi |
je no_app_move |
cld |
rep movsb ; move the app image to the new position |
no_app_move: |
call save_new_position_for_threads |
call check_for_thread_mem |
mov [application_table_status],0 |
mov [esp+36],dword 0 ; eax <- 0 ; successfull |
ret |
rfind_free_ret_2: |
mem_resize_unsuccess: |
mov [application_table_status],0 |
mov [esp+36],dword 1 ; eax <- 1 ; unsuccessfull |
ret |
no_application_mem_resize: |
ret |
align 4 |
find_free_mem: |
push eax |
push ebx |
push ecx |
push edx |
push edi |
call find_free_process_slot |
mov eax,[new_process_place] |
cmp eax,max_processes |
jg find_free_ret_2 |
cmp [thread_create],1 |
je thread_c |
mov esi,[0xfe84] |
add edi,esi |
dec edi |
mov eax,2 |
cmp dword [0x3004],1 |
je findf4 |
fgdt: |
mov edx,2 |
findgdtl1: |
mov ecx,edx |
shl ecx,3 |
; eax run base -> ebx limit |
mov al,[ecx+gdts+ app_code-3 +4] |
mov ah,[ecx+gdts+ app_code-3 +7] |
shl eax,16 |
mov ax,[ecx+gdts+ app_code-3 +2] |
;!!mem |
cmp eax,std_application_base_address |
jz findfl3 |
;!!mem |
movzx ebx,word [ecx+gdts+ app_code-3 +0] |
shl ebx,12 |
add ebx,eax |
cmp eax,edi |
jg findfl3 |
cmp ebx,esi |
jb findfl3 |
add esi,4096 |
add edi,4096 |
cmp edi,[0xfe8c] ; < c_memory |
jbe fgdt |
jmp find_free_ret_2 |
findfl3: |
inc edx |
cmp edx,[check_processes] |
jbe findgdtl1 |
findfl1: |
thread_c: |
mov eax,[new_process_place] |
findf4: |
mov [first_gdt_search],eax |
mov [gdt_place],eax |
mov ecx,eax |
shl ecx,3 |
inc edi |
sub edi,esi |
add edi,4095 |
shr edi,12 |
dec edi |
; code |
mov eax,esi |
mov ebx,edi |
mov [ecx+gdts+ app_code-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_code-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_code-3 +7], ah ; base 31:24 |
mov [ecx+gdts+ app_code-3 +0], bx ; limit |
mov [ecx+gdts+ app_code-3 +5], word 11010000b *256 +11111010b |
; data |
mov eax,esi |
mov [ecx+gdts+ app_data-3 +2], ax ; base 0:15 |
shr eax,16 |
mov [ecx+gdts+ app_data-3 +4], al ; base 23:16 |
mov [ecx+gdts+ app_data-3 +7], ah ; base 31:24 |
mov [ecx+gdts+ app_data-3 +0], bx ; limit |
mov [ecx+gdts+ app_data-3 +5], word 11010000b *256 +11110010b |
push esi |
mov esi,process_loading |
call sys_msg_board_str |
pop esi |
find_free_ret: |
pop edi |
pop edx |
pop ecx |
pop ebx |
pop eax |
ret |
find_free_ret_2: |
cmp [dec3004],0 |
je no3004inc |
dec dword [0x3004] |
no3004inc: |
pop edi |
pop edx |
pop ecx |
pop ebx |
pop eax |
mov esi,0 |
ret |
get_app_params: |
push eax |
cmp [0x90000+6],word '00' |
jne no_00_header |
mov eax,[0x90000+12] |
mov [app_start],eax |
mov eax,[0x90000+16] |
mov [app_i_end],eax |
mov eax,[0x90000+20] |
mov [app_mem],eax |
shr eax,1 |
sub eax,0x10 |
mov [app_esp],eax |
mov eax,[0x90000+24] |
mov [app_i_param],eax |
mov [app_i_icon],dword 0 |
pop eax |
mov esi,1 |
ret |
no_00_header: |
cmp [0x90000+6],word '01' |
jne no_01_header |
mov eax,[0x90000+12] |
mov [app_start],eax |
mov eax,[0x90000+16] |
mov [app_i_end],eax |
mov eax,[0x90000+20] |
mov [app_mem],eax |
mov eax,[0x90000+24] |
mov [app_esp],eax |
mov eax,[0x90000+28] |
mov [app_i_param],eax |
mov eax,[0x90000+32] |
mov [app_i_icon],eax |
pop eax |
mov esi,1 |
ret |
no_01_header: |
pop eax |
mov esi,0 |
ret |
start_application_fl: |
jmp new_start_application_fl |
;************************************************************************ |
start_application_floppy: |
jmp new_start_application_floppy |
;******************************************************************** |
start_application_hd: |
jmp new_start_application_hd |
uglobal |
threadstring dd 0x0 |
new_process_place dd 0x0 |
check_processes dd 0x0 |
dec3004 db 0x0 |
app_start dd 0x0 |
app_i_end dd 0x0 |
app_mem dd 0x0 |
app_esp dd 0x0 |
app_i_param dd 0x0 |
app_i_icon dd 0x0 |
app_mem_pos dd 0x0 |
thread_create dd 0x0 |
gdt_place dd 0x0 |
endg |
iglobal |
hd_app_string db 'HDAPP ' |
process_loading db 'K : Process - loading ',13,10,0 |
process_running db 'K : Process - done',13,10,0 |
first_gdt_search dd 0x2 |
endg |
sys_threads: |
; eax=1 create thread |
; |
; ebx=thread start |
; ecx=thread stack value |
; |
; on return : eax = pid |
jmp new_sys_threads |
cli |
cmp [application_table_status],0 |
je stth9 |
sti |
call change_task |
jmp sys_threads |
stth9: |
call set_application_table_status |
sti |
cmp eax,1 |
jne no_sys_thread_create |
cli |
mov eax,[0x3010] |
mov eax,[eax+0x10] |
mov [app_mem_pos],eax |
mov [app_i_param],0 |
mov [app_i_icon],0 |
mov [app_start],ebx |
mov [app_esp],ecx |
mov ebx,[0x3000] |
shl ebx,8 |
add ebx,0x80000 |
mov [threadstring],ebx |
mov ebx,[ebx+0x8c] |
mov [app_mem],ebx |
mov esi,[app_mem_pos] |
mov edi,[app_mem] |
add edi,esi |
dec edi |
mov [thread_create],1 |
call find_free_mem |
cmp esi,0 |
jne th_cr1 |
mov [application_table_status],0 |
mov eax,1 ; no free memory |
sti |
ret |
th_cr1: |
push dword 0 |
push dword [threadstring] |
jmp add_app_parameters |
no_sys_thread_create: |
mov eax,-1 |
mov [application_table_status],0 |
ret |
find_free_process_slot: |
pusha |
mov ebx,[0x3004] |
mov [check_processes],ebx |
inc ebx |
mov [new_process_place],ebx |
mov ebx,2 |
newfps: |
mov eax,ebx |
;imul eax,0x20 |
shl eax, 5 |
add eax,0x3000+0xa |
cmp [eax],byte 9 |
je ffpl |
inc ebx |
cmp ebx,[0x3004] |
jbe newfps |
;mov [dec3004],0 |
mov [dec3004],1 |
shl ebx,5 |
mov [0x3000+0xa+ebx],byte 9 |
inc dword [0x3004] |
popa |
ret |
ffpl: |
;mov [dec3004],1 |
;dec dword [0x3004] |
mov [dec3004],0 |
mov [new_process_place],ebx |
popa |
ret |
add_app_parameters: |
; returns: eax = pid or -1 if unsuccesfull |
cmp [app_i_param],dword 0 ; parameter |
jz no_app_params |
xor eax, eax |
mov edi,[app_i_param] |
add edi,[app_mem_pos] |
mov ecx,256/4 |
cld |
rep stosd |
mov esi,[esp+4] |
test esi, esi |
jz no_app_params |
mov eax,[app_i_param] |
add eax,[app_mem_pos] |
mov edi,eax |
mov ecx,256 |
cld |
app_new_param: |
cmp [esi],byte 0 |
jz no_app_params |
movsb |
loop app_new_param |
no_app_params: |
;inc dword [0x3004] ; increase number of processes |
mov ebx,[new_process_place] |
mov edi,ebx ; clear 0x80000 (256 bytes) |
shl edi,8 |
add edi,0x80000 |
mov ecx,256 / 4 |
mov eax,0 |
cld |
rep stosd |
shl ebx,5 ; * 32 +0x3000 |
add ebx,0x3000 |
mov al,byte [new_process_place] ; screen id ? |
mov [ebx+0xe],al |
mov [ebx],dword 1+2+4 ; report events: windowdraw, key, button |
inc dword [process_number] ; process id number |
mov eax,[process_number] |
mov [ebx+4],eax |
mov ecx,ebx ; set draw limits |
add ecx,draw_data-0x3000 |
mov [ecx+0],dword 0 |
mov [ecx+4],dword 0 |
mov eax,[0xfe00] |
mov [ecx+8],eax |
mov eax,[0xfe04] |
mov [ecx+12],eax |
mov eax,[app_mem_pos] ; position in memory |
mov [ebx+0x10],eax |
; TSS |
xor ebx,ebx |
cmp [thread_create],ebx |
jnz clone_cr3_table |
mov eax,[new_process_place] |
call create_app_cr3_table |
jmp set_cr3 |
clone_cr3_table: |
; mov eax,[new_process_place] |
; mov ebx,[0x3000] |
; call addreference_app_cr3_table |
mov eax,[0x3000] |
call get_cr3_table |
set_cr3: |
add eax,8+16 |
mov [l.cr3],eax |
mov eax,[app_start] |
mov [l.eip],eax |
mov eax,[app_esp] |
mov [l.esp],eax |
mov ebx,[new_process_place] ; gdt's |
shl ebx,3 |
mov ax,app_code |
add ax,bx |
mov [l.cs],ax |
mov ax,app_data |
add ax,bx |
mov [l.ss],ax |
mov [l.ds],ax |
mov [l.es],ax |
mov [l.fs],ax |
mov ax,graph_data |
mov [l.gs],ax |
mov [l.io],word 128 |
mov [l.eflags],dword 0x11202 |
mov [l.ss0], os_data |
;mov [l.ss1], ring1_data |
;mov [l.ss2], ring2_data |
; [Ivan 07.03.2005] |
mov [l.esp0], 0x8000 ;0x55000 ; used by i38 handler |
; [/Ivan 07.03.2005] |
mov [l.esp1], 0x56000 |
mov [l.esp2], 0x57000 |
mov eax,tss_sceleton ; move tss to tss_data+ |
mov ebx,[new_process_place] |
imul ebx,tss_step |
add ebx,tss_data |
mov ecx,120 |
call memmove |
; Add IO access table |
or eax, -1 |
mov edi, [new_process_place] |
imul edi, tss_step |
add edi, tss_data + 128 |
mov ecx, 2048 ; for 2048 * 4 * 8 bits = 65536 ports |
cld |
rep stosd |
; make sure gdt is pointing to the process |
; and not to i40 handler |
mov ecx,ebx |
mov edi,[new_process_place] |
; imul edi,8 |
shl edi, 3 |
mov [edi+gdts+ tss0 +0], word tss_step ; limit 0:15 |
mov [edi+gdts+ tss0 +2], cx ; base 0:15 |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0 +4], al ; base 23:16 |
mov [edi+gdts+ tss0 +7], ah ; base 31:24 |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
pop eax |
pop ebx |
mov ebx,[new_process_place] ; save name of the process |
shl ebx,8 |
add ebx,0x80000 |
mov ecx,11 |
call memmove |
mov ebx,[new_process_place] ; save image size |
shl ebx,8 |
add ebx,0x80000+0x8C |
mov eax,[app_mem] |
mov [ebx],eax |
mov [0xf400],byte 0 ; empty keyboard buffer |
mov [0xf500],byte 0 ; empty button buffer |
mov [application_table_status],0 |
mov eax,[process_number] |
mov ebx,[new_process_place] |
shl ebx, 5 ;imul ebx,0x20 |
mov [0x3000+ebx+0xa],byte 0 |
mov edi,[new_process_place] |
shl edi,5 |
add edi,window_data |
mov ebx,[new_process_place] |
movzx esi, word [0xC000 + ebx*2] |
lea esi, [0xC400 + esi*2] |
call windowactivate |
sti |
push esi |
mov esi,process_running |
call sys_msg_board_str |
pop esi |
ret |
iglobal |
process_terminating db 'K : Process - terminating',13,10,0 |
process_terminated db 'K : Process - done',13,10,0 |
endg |
terminate: ; terminate application |
push esi |
mov esi,process_terminating |
call sys_msg_board_str |
pop esi |
;start memory manager code |
; mov eax,esi |
; call MEM_Heap_Clean |
;end memory manager code |
cli |
cmp [application_table_status],0 |
je term9 |
sti |
call change_task |
jmp terminate |
term9: |
call set_application_table_status |
mov eax,esi |
call dispose_app_cr3_table |
mov [first_gdt_search],0x2 ; start gdt search from beginning |
cmp [prev_user_of_fpu],esi ; if user fpu last -> fpu user = 1 |
jne fpu_ok_1 |
mov [prev_user_of_fpu],1 |
fpu_ok_1: |
mov [0xf400],byte 0 ; empty keyboard buffer |
mov [0xf500],byte 0 ; empty button buffer |
mov ecx,esi ; clear memory reserv. |
shl ecx,3 |
mov [ecx+gdts+ app_code-3 +0],dword 0 |
mov [ecx+gdts+ app_code-3 +4],dword 0 |
mov [ecx+gdts+ app_data-3 +0],dword 0 |
mov [ecx+gdts+ app_data-3 +4],dword 0 |
mov edi, esi |
; shl edi, 5 |
; add edi, 0x3000 |
; cmp [edi+0xa],byte 3 ; if normal terminate then clear int40 handler |
; jne nocl40 |
; mov edi,esi ; free the used interrupt 0x40 handler |
; shl edi, 8 ;imul edi,256 |
; mov eax,[edi+0x80000+0xb0] |
; cmp eax,0 ; is application using a systemcall interrupt ? |
; je nocl40 |
mov [usedi40+eax],byte 0 |
; mov edi,8 |
; imul edi,eax |
mov edi, eax |
shl edi, 3 |
mov [edi+tss0sys_l +5], word 01010000b *256 +11101001b |
; mov edi,128 |
; imul edi,eax |
mov edi, eax |
shl edi, 7 |
mov [edi+0x298000+l.eip-tss_sceleton],dword i40 |
mov [edi+0x298000+l.eflags-tss_sceleton],dword 0x11002 |
mov ebx,eax |
shl ebx, 12 ;imul ebx,4096 |
add ebx,sysint_stack_data |
mov [edi+0x298000+l.esp-tss_sceleton],ebx |
nocl40: |
mov ecx,esi ; remove buttons |
bnewba2: |
mov edi,[0xfe88] |
mov eax,edi |
cld |
movzx ebx,word [edi] |
inc bx |
bnewba: |
dec bx |
jz bnmba |
add eax,0x10 |
cmp cx,[eax] |
jnz bnewba |
pusha |
mov ecx,ebx |
inc ecx |
shl ecx,4 |
mov ebx,eax |
add eax,0x10 |
call memmove |
dec dword [edi] |
popa |
jmp bnewba2 |
bnmba: |
pusha ; save window coordinates for window restoring |
cld |
shl esi,5 |
add esi,window_data |
mov ax,[esi+0] |
mov word [dlx],ax |
mov bx,[esi+8] |
add ax,bx |
mov word [dlxe],ax |
mov ax,[esi+4] |
mov word [dly],ax |
mov bx,[esi+12] |
add ax,bx |
mov word [dlye],ax |
mov [esi+0],word 0 |
mov [esi+8],word 5 |
mov ax,[0xFE04] |
mov [esi+4],ax |
mov [esi+12],word 5 |
xor eax, eax |
mov [esi+16],eax;dword 0 |
mov [esi+20],eax;dword 0 |
mov [esi+24],eax;dword 0 |
mov [esi+28],eax;dword 0 |
popa |
pusha |
mov edi,esi |
shl edi,5 |
add edi,window_data |
mov ecx,32/4 |
xor eax, eax |
; cld |
rep stosd |
mov eax,[0xFE04] ; set window to start from maxy+1 |
add eax,2 |
mov edi,esi |
shl edi,5 |
add edi,window_data |
mov [edi+4],eax |
popa |
pusha |
mov edi,esi |
shl edi,5 |
add edi,draw_data |
mov ecx,32/4 |
xor eax, eax |
; cld |
rep stosd |
popa |
pusha ; at 0x80000+ |
mov edi,esi |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax, eax |
; cld |
rep stosd |
popa |
pusha ; name to spaces |
mov edi,esi |
shl edi,8 |
add edi,0x80000 |
mov ecx,11 |
mov eax,' ' |
; cld |
rep stosb |
popa |
pusha ; C000 --> C400 |
mov eax, 0xc000 |
mov esi, 0 |
nlc40: |
add eax, 2 |
inc esi |
cmp esi, [0x3004] |
jae nlc41 |
movzx ecx, word [eax] |
mov [0xC400 + ecx*2], si |
jmp nlc40 |
nlc41: |
; ivan 08.12.2004 begin |
;mov ebx, [0x3004] |
;dec ebx |
;lea esi, [0xC400 + ebx*2] |
;call windowactivate |
; ivan 08.12.2004 end |
popa |
pusha ; remove hd1 reservation |
mov edx,esi |
shl edx, 5 ;imul edx,0x20 |
add edx,0x3000 |
mov edx,[edx+4] |
cmp [hd1_status],edx |
jne no_hd1_s_remove |
mov [hd1_status],0 |
no_hd1_s_remove: |
popa |
pusha ; remove all irq reservations |
mov edx,esi |
shl edx, 5 ;imul edx,0x20 |
add edx,0x3000 |
mov edx,[edx+4] |
mov edi,irq_owner |
mov ecx,16 |
newirqfree: |
cmp [edi],edx |
jne nofreeirq |
mov [edi],dword 0 |
nofreeirq: |
add edi,4 |
loop newirqfree |
popa |
pusha ; remove all port reservations |
mov edx,esi |
shl edx, 5 ;imul edx,0x20 |
add edx,0x3000 |
mov edx,[edx+4] |
rmpr0: |
mov esi,[0x2d0000] |
cmp esi,0 |
je rmpr9 |
rmpr3: |
mov edi,esi |
shl edi,4 |
add edi,0x2d0000 |
cmp edx,[edi] |
je rmpr4 |
dec esi |
jnz rmpr3 |
jmp rmpr9 |
rmpr4: |
mov ecx,256 |
sub ecx,esi |
shl ecx,4 |
mov esi,edi |
add esi,16 |
cld |
rep movsb |
dec dword [0x2d0000] |
jmp rmpr0 |
rmpr9: |
popa |
mov edi,esi ; do not run this process slot |
shl edi, 5 ;imul edi,0x20 |
; add edi,0x3000 |
mov [edi+0x300A],byte 9 |
; call systest |
sti ; .. and life goes on |
; movzx eax,word [dlx] |
; movzx ebx,word [dly] |
; movzx ecx,word [dlxe] |
; movzx edx,word [dlye] |
call calculatescreen |
xor eax, eax |
xor esi, esi |
call redrawscreen |
mov [0xfff4],byte 0 ; no mouse background |
mov [0xfff5],byte 0 ; draw mouse |
mov [application_table_status],0 |
mov esi,process_terminated |
call sys_msg_board_str |
;* start code - fix error redraw for terminate (2) - Mario79 |
; cmp [draw_present],1 |
; je no_draw_background_temp |
; mov [0xfff0],byte 1 |
;no_draw_background_temp: |
; mov [draw_present],0 |
ret |
;draw_present db 0 |
;* end code - fix error redraw for terminate (2) - Mario79 |
iglobal |
boot_sched_1 db 'Building gdt tss pointer',0 |
;boot_sched_2 db 'Building gdt gate pointer',0 |
boot_sched_3 db 'Building interrupt table - TSS',0 |
boot_sched_3_2 db 'Building interrupt table - GDT',0 |
boot_sched_3_3 db 'Building interrupt table - IDT',0 |
boot_sched_4 db 'Building syscall interrupt table',0 |
endg |
build_scheduler: |
; { Ivan 06.03.2005 |
mov edi, usedi40 |
mov ecx, 256/4 |
xor eax, eax |
rep stosd |
; } Ivan 06.03.2005 |
mov esi,boot_sched_1 |
call boot_log |
call build_process_gdt_tss_pointer |
; mov esi,boot_sched_2 |
; call boot_log |
; call build_process_gdt_gate_pointer |
mov esi,boot_sched_3 |
call boot_log |
call build_interrupt_table |
mov esi,boot_sched_4 |
call boot_log |
call build_syscall_interrupt_table |
ret |
/kernel/trunk/core/syscall.inc |
---|
0,0 → 1,238 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
i40: |
cli |
mov edi,[0x3000] |
mov eax,edi |
shl edi, 3 |
;clear busy flag in application's TSS |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
;save GDT TSS entry |
mov edx,[edi+tss0_l] |
mov [reg1+eax*4],edx |
mov edx,[edi+tss0_l+4] |
mov [reg2+eax*4],edx |
;and then write there i40's descriptor |
mov edx,[tss0sys_l+edi] |
mov [edi+tss0_l],edx |
mov edx,[tss0sys_l+edi+4] |
mov [edi+tss0_l+4],edx |
shl edi,5 |
mov [edi+0x80000+0xB0],eax ; used i40 handler |
; for syscall trace function |
call save_registers |
mov esi, [0x3000] |
imul esi, tss_step |
add esi, tss_data |
; esi holds address of TSS of interupted program |
; load first 3 registers |
mov eax,[esi+l.eax-tss_sceleton] |
mov ebx,[esi+l.ebx-tss_sceleton] |
mov ecx,[esi+l.ecx-tss_sceleton] |
; save current registers |
; stack may be modified by a system function to return some value to caller! |
pushad |
; load all registers from TSS of the application, in crossed order (why?) |
mov edi,[esi+l.eax-tss_sceleton] |
mov eax,[esi+l.ebx-tss_sceleton] |
mov ebx,[esi+l.ecx-tss_sceleton] |
mov ecx,[esi+l.edx-tss_sceleton] |
mov edx,[esi+l.esi-tss_sceleton] |
mov esi,[esi+l.edi-tss_sceleton] |
; enable interupts - a task switch or an IRQ _CAN_ interrupt i40 handler |
sti |
; eax doesn't need to be saved, but... |
push eax |
and edi,0xff |
call dword [servetable+edi*4] |
pop eax |
cli |
; return saved and probably even changed regs |
popad |
; <Ivan 05.03.2005> esi already loaded - look above "pusha" |
;mov esi,[0x3000] |
;imul esi,tss_step |
;add esi,tss_data |
; </Ivan 05.03.2005> |
; modify 3 program's registers (in its TSS) |
mov [esi+l.eax-tss_sceleton], eax |
mov [esi+l.ebx-tss_sceleton], ebx |
mov [esi+l.ecx-tss_sceleton], ecx |
; calculate app's TSS address |
mov ebx, [0x3000] |
shl ebx, 3 |
add ebx, tss0_l |
mov ecx, [0x3000] |
; restore saved TSS descriptor |
mov eax, [reg1+ecx*4] |
mov [ebx], eax |
mov eax, [reg2+ecx*4] |
mov [ebx+4], eax |
xor eax, eax |
mov edi, [0x3000] ; no syscall interrupt in use anymore |
shl edi, 8 |
mov [edi+0x80000+0xB0],eax |
; clear busy flag in TSS of this handler |
mov edi, [0x3000] |
shl edi, 3 |
mov [edi+tss0sys_l +5], word 01010000b *256 +11101001b |
add edi,tss0 |
mov [0xB004], di |
jmp pword [0xB000] |
jmp i40 |
label reg1 dword at 0x6000 |
label reg2 dword at 0x6400 |
label usedi40 byte at 0x6800 |
uglobal |
schd dd 0x0 |
endg |
align 4 |
save_registers: |
mov esi,[0x3000] |
imul esi,tss_step |
add esi,tss_data |
mov eax,[esi+l.eax-tss_sceleton] |
mov ebx,[esi+l.ebx-tss_sceleton] |
mov ecx,[esi+l.ecx-tss_sceleton] |
mov edx,[esi+l.edx-tss_sceleton] |
mov edi,[esi+l.edi-tss_sceleton] |
mov ebp,[esi+l.ebp-tss_sceleton] |
mov esi,[esi+l.esi-tss_sceleton] |
push eax ecx esi edi |
mov esi,[0x3010] |
mov eax,[esi+0x4] |
mov esi,esp |
inc [save_syscall_count] |
mov edi,[save_syscall_count] |
and edi,0xF |
shl edi,6 |
add edi,save_syscall_data+32 |
mov [edi-32],eax |
mov ecx,32 / 4 |
cld |
rep movsd |
pop edi esi ecx eax |
ret |
uglobal |
save_syscall_count dd 0x0 |
endg |
label save_syscall_data dword at 0x5000 |
iglobal |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable: |
dd sys_drawwindow ; 0-DrawWindow |
dd syscall_setpixel ; 1-SetPixel |
dd sys_getkey ; 2-GetKey |
dd sys_clock ; 3-GetTime |
dd syscall_writetext ; 4-WriteText |
dd delay_hs ; 5-DelayHs |
dd syscall_openramdiskfile ; 6-OpenRamdiskFile |
dd syscall_putimage ; 7-PutImage |
dd sys_button ; 8-DefineButton |
dd sys_cpuusage ; 9-GetProcessInfo |
dd sys_waitforevent ; 10-WaitForEvent |
dd sys_getevent ; 11-CheckForEvent |
dd sys_redrawstat ; 12-BeginDraw and EndDraw |
dd syscall_drawrect ; 13-DrawRect |
dd syscall_getscreensize ; 14-GetScreenSize |
dd sys_background ; 15-bgr |
dd sys_cachetodiskette ; 16-FlushFloppyCache |
dd sys_getbutton ; 17-GetButton |
dd syscall_system ; 18-Shutdown,KillApp,WindowActivate |
dd syscall_startapp ; 19-StartApp |
dd sys_midi ; 20-ResetMidi and OutputMidi |
dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. |
dd sys_settime ; 22-setting date,time,clock and alarm-clock |
dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent |
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist |
dd sys_sb16 ; 25-SetSb16 |
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. |
dd sys_wss ; 27-SetWssMainVol and SetWssCdVol |
dd sys_sb16II ; 28-SetSb16 |
dd sys_date ; 29-GetDate |
dd syscall_readhd ; 30-ReadHd |
dd syscall_starthdapp ; 31-StartHdApp |
dd syscall_delramdiskfile ; 32-DelRamdiskFile |
dd syscall_writeramdiskfile; 33-WriteRamdiskFile |
dd read_floppy_file ; 34-ReadFloppyDrive |
dd syscall_getpixel ; 35-GetPixel |
dd syscall_readstring ; 36-ReadString (not yet ready) |
dd readmousepos ; 37-GetMousePosition_ScreenRelative,. |
dd syscall_drawline ; 38-DrawLine |
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. |
dd set_app_param ; 40-WantEvents |
dd syscall_getirqowner ; 41-GetIrqOwner |
dd get_irq_data ; 42-ReadIrqData |
dd sys_outport ; 43-SendDeviceData |
dd sys_programirq ; 44-ProgramIrqs |
dd reserve_free_irq ; 45-ReserveIrq and FreeIrq |
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea |
dd display_number ; 47-WriteNum |
dd display_settings ; 48-SetRedrawType and SetButtonType |
dd syscall_appints ; 49-AppInts |
dd random_shaped_window ; 50-Window shape & scale |
dd syscall_threads ; 51-Threads |
dd stack_driver_stat ; 52-Stack driver status |
dd socket ; 53-Socket interface |
dd user_events ; 54-User events |
dd sound_interface ; 55-Sound interface |
dd write_to_hd ; 56-Write a file to hd |
dd delete_from_hd ; 57-Delete a file from hd |
dd file_system ; 58-Common file system interface |
dd sys_trace ; 59-System call trace |
dd new_sys_ipc ; 60-Inter Process Communication |
dd sys_gs ; 61-Direct graphics access |
dd sys_pci ; 62-PCI functions |
dd sys_msg_board ; 63-System message board |
dd sys_resize_app_memory ; 64-Resize application memory usage |
dd undefined_syscall ; 65-UTF |
dd sys_process_def ; 66-Process definitions - keyboard |
dd sys_window_move ; 67-Window move or resize |
dd sys_internal_services ; 68-Some internal services |
times 255 - ( ($-servetable) /4 ) dd undefined_syscall |
dd sys_end ; -1-end application |
endg |