kolibrios/kernel/branches/kolibri_pe/core/dll.inc

1243 lines
27 KiB
PHP
Raw Permalink Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
DRV_COMPAT equ 5 ;minimal required drivers version
DRV_CURRENT equ 5 ;current drivers model version
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
PID_KERNEL equ 1 ;os_idle thread
align 4
proc attach_int_handler stdcall, irq:dword, handler:dword, access_rights:dword
push ebx
mov ebx, [irq] ;irq num
test ebx, ebx
jz .err
cmp ebx, 15 ; hidnplayr says: we only have 16 IRQ's
ja .err
mov eax, [handler]
test eax, eax
jz .err
cmp [irq_owner + 4 * ebx], 0
je @f
mov ecx, [irq_rights + 4 * ebx] ; Rights : 0 - full access, 1 - read only, 2 - forbidden
test ecx, ecx
jnz .err
@@:
mov [irq_tab+ebx*4], eax
mov eax, [access_rights]
mov [irq_rights + 4 * ebx], eax
mov [irq_owner + 4 * ebx], PID_KERNEL ; all handlers belong to a kernel
stdcall enable_irq, [irq]
pop ebx
mov eax, 1
ret
.err:
pop ebx
xor eax, eax
ret
endp
uglobal
irq_rights rd 16
endg
proc get_int_handler stdcall, irq:dword
mov eax, [irq]
cmp [irq_rights + 4 * eax], dword 1
ja .err
mov eax, [irq_tab + 4 * eax]
ret
.err:
xor eax, eax
ret
endp
align 4
proc detach_int_handler
ret
endp
align 4
proc enable_irq stdcall, irq_line:dword
mov ebx, [irq_line]
mov edx, 0x21
cmp ebx, 8
jb @F
mov edx, 0xA1
sub ebx,8
@@:
in al,dx
btr eax, ebx
out dx, al
ret
endp
align 16
;; proc irq_serv
irq_serv:
.irq_1:
push 1
jmp .main
align 4
.irq_2:
push 2
jmp .main
align 4
.irq_3:
push 3
jmp .main
align 4
.irq_4:
push 4
jmp .main
align 4
.irq_5:
push 5
jmp .main
align 4
.irq_6:
push 6
jmp .main
align 4
.irq_7:
push 7
jmp .main
align 4
.irq_8:
push 8
jmp .main
align 4
.irq_9:
push 9
jmp .main
align 4
.irq_10:
push 10
jmp .main
align 4
.irq_11:
push 11
jmp .main
align 4
.irq_12:
push 12
jmp .main
align 4
.irq_13:
push 13
jmp .main
align 4
.irq_14:
push 14
jmp .main
align 4
.irq_15:
push 15
jmp .main
align 16
.main:
save_ring3_context
mov eax, [esp + 32]
mov bx, sel_app_data
mov ds, bx
mov es, bx
cmp [v86_irqhooks+eax*8], 0
jnz v86_irq
mov ebx, [irq_tab+eax*4]
test ebx, ebx
jz .exit
call ebx
mov [check_idle_semaphore],5
.exit:
cmp dword [esp + 32], 8
mov al, 0x20
jb @f
out 0xa0, al
@@:
out 0x20, al
restore_ring3_context
add esp, 4
iret
align 4
proc get_notify stdcall, p_ev:dword
.wait:
mov ebx,[current_slot]
test dword [ebx+APPDATA.event_mask],EVENT_NOTIFY
jz @f
and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
mov edi, [p_ev]
mov dword [edi], EV_INTR
mov eax, [ebx+APPDATA.event]
mov dword [edi+4], eax
ret
@@:
call change_task
jmp .wait
endp
align 4
_PciRead32:
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 6
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
align 4
_PciRead16:
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 5
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
align 4
_PciRead8:
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 4
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
align 4
_PciWrite8:
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 8
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
align 4
_PciWrite16:
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 9
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
align 4
_PciWrite32:
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 10
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
align 4
proc srv_handler stdcall, ioctl:dword
mov esi, [ioctl]
test esi, esi
jz .err
mov edi, [esi+handle]
cmp [edi+SRV.magic], ' SRV'
jne .fail
cmp [edi+SRV.size], SRV_SIZE
jne .fail
stdcall [edi+SRV.srv_proc], esi
ret
.fail:
xor eax, eax
not eax
mov [esi+output], eax
mov [esi+out_size], 4
ret
.err:
xor eax, eax
not eax
ret
endp
; param
; ebx= io_control
;
; retval
; eax= error code
align 4
srv_handlerEx:
cmp ebx, OS_BASE
jae .fail
mov eax, [ebx+handle]
cmp [eax+SRV.magic], ' SRV'
jne .fail
cmp [eax+SRV.size], SRV_SIZE
jne .fail
stdcall [eax+SRV.srv_proc], ebx
ret
.fail:
or eax, -1
ret
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
align 4
proc get_service stdcall, sz_name:dword
mov eax, [sz_name]
test eax, eax
jnz @F
ret
@@:
mov edx, [srv.fd]
@@:
cmp edx, srv.fd-SRV_FD_OFFSET
je .not_load
stdcall strncmp, edx, [sz_name], 16
test eax, eax
je .ok
mov edx, [edx+SRV.fd]
jmp @B
.not_load:
pop ebp
jmp load_driver
.ok:
mov eax, edx
ret
endp
align 4
_RegService:
proc reg_service stdcall, name:dword, handler:dword
push ebx
xor eax, eax
cmp [name], eax
je .fail
cmp [handler], eax
je .fail
mov eax, SRV_SIZE
call malloc ;call alloc_service
test eax, eax
jz .fail
push esi
push edi
mov edi, eax
mov esi, [name]
mov ecx, 16/4
rep movsd
pop edi
pop esi
mov [eax+SRV.magic], ' SRV'
mov [eax+SRV.size], SRV_SIZE
mov ebx, srv.fd-SRV_FD_OFFSET
mov edx, [ebx+SRV.fd]
mov [eax+SRV.fd], edx
mov [eax+SRV.bk], ebx
mov [ebx+SRV.fd], eax
mov [edx+SRV.bk], eax
mov ecx, [handler]
mov [eax+SRV.srv_proc], ecx
pop ebx
ret
.fail:
xor eax, eax
pop ebx
ret
endp
align 4
proc get_proc stdcall, exp:dword, sz_name:dword
mov edx, [exp]
.next:
mov eax, [edx]
test eax, eax
jz .end
push edx
stdcall strncmp, eax, [sz_name], 16
pop edx
test eax, eax
jz .ok
add edx,8
jmp .next
.ok:
mov eax, [edx+4]
.end:
ret
endp
align 4
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
@@:
stdcall strncmp, [pSym], [sz_sym], 8
test eax,eax
jz .ok
add [pSym], 18
dec [count]
jnz @b
xor eax, eax
ret
.ok:
mov ebx, [pSym]
mov eax, [ebx+8]
ret
endp
align 4
get_curr_task:
mov eax,[CURRENT_TASK]
shl eax, 8
ret
align 4
proc get_fileinfo stdcall, file_name:dword, info:dword
locals
cmd dd ?
offset dd ?
dd ?
count dd ?
buff dd ?
db ?
name dd ?
endl
xor eax, eax
mov ebx, [file_name]
mov ecx, [info]
mov [cmd], 5
mov [offset], eax
mov [offset+4], eax
mov [count], eax
mov [buff], ecx
mov byte [buff+4], al
mov [name], ebx
mov eax, 70
lea ebx, [cmd]
int 0x41
ret
endp
align 4
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
bytes:dword
locals
cmd dd ?
offset dd ?
dd ?
count dd ?
buff dd ?
db ?
name dd ?
endl
xor eax, eax
mov ebx, [file_name]
mov ecx, [off]
mov edx, [bytes]
mov esi, [buffer]
mov [cmd], eax
mov [offset], ecx
mov [offset+4], eax
mov [count], edx
mov [buff], esi
mov byte [buff+4], al
mov [name], ebx
pushad
push eax
lea eax, [cmd]
call file_system_lfn
pop eax
popad
ret
endp
; description
; allocate kernel memory and loads the specified file
;
; param
; file_name= full path to file
;
; retval
; eax= file image in kernel memory
; ebx= size of file
;
; warging
; You mast call mem_free() to delete each file
; loaded by the load_file() function
align 4
_LoadFile:
_load_file@4:
proc load_file stdcall, file_name:dword
locals
attr dd ?
flags dd ?
cr_time dd ?
cr_date dd ?
acc_time dd ?
acc_date dd ?
mod_time dd ?
mod_date dd ?
file_size dd ?
file dd ?
file2 dd ?
endl
push esi
push edi
lea eax, [attr]
stdcall get_fileinfo, [file_name], eax
test eax, eax
jnz .fail
mov ecx, [file_size]
cmp ecx, 1024*1024*16
ja .fail
mov edx, PG_SW
call @mem_alloc@8
mov [file], eax
test eax, eax
jz .fail
stdcall read_file, [file_name], eax, dword 0, [file_size]
cmp ebx, [file_size]
jne .cleanup
mov eax, [file]
cmp dword [eax], 0x4B43504B
jne .exit
mov ecx, [eax+4]
mov [file_size], ecx
mov edx, PG_SW
call @mem_alloc@8
test eax, eax
jz .cleanup
mov [file2], eax
stdcall unpack, [file], eax
mov ecx, [file]
call @mem_free@4
mov eax, [file2]
mov ebx, [file_size]
.exit:
push eax
lea edi, [eax+ebx] ;cleanup remain space
mov ecx, 4096 ;from file end
and ebx, 4095
jz @f
sub ecx, ebx
xor eax, eax
cld
rep stosb
@@:
mov ebx, [file_size]
pop eax
pop edi
pop esi
ret
.cleanup:
mov ecx, [file]
call @mem_free@4
.fail:
xor eax, eax
xor ebx, ebx
pop edi
pop esi
ret
endp
align 4
proc get_proc_ex stdcall, proc_name:dword, imports:dword
.look_up:
mov edx, [imports]
test edx, edx
jz .end
mov edx, [edx]
test edx, edx
jz .end
.next:
mov eax, [edx]
test eax, eax
jz .next_table
push edx
stdcall strncmp, eax, [proc_name], 16
pop edx
test eax, eax
jz .ok
add edx,8
jmp .next
.next_table:
add [imports], 4
jmp .look_up
.ok:
mov eax, [edx+4]
ret
.end:
xor eax, eax
ret
endp
align 4
proc fix_coff_symbols stdcall, sec:dword, symbols:dword,\
sym_count:dword, strings:dword, imports:dword
locals
retval dd ?
endl
mov edi, [symbols]
mov [retval], 1
.fix:
movzx ebx, [edi+CSYM.SectionNumber]
test ebx, ebx
jnz .internal
mov eax, dword [edi+CSYM.Name]
test eax, eax
jnz @F
mov edi, [edi+4]
add edi, [strings]
@@:
push edi
stdcall get_proc_ex, edi,[imports]
pop edi
xor ebx, ebx
test eax, eax
jnz @F
mov esi, msg_unresolved
call sys_msg_board_str
mov esi, edi
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
mov [retval],0
@@:
mov edi, [symbols]
mov [edi+CSYM.Value], eax
jmp .next
.internal:
cmp bx, -1
je .next
cmp bx, -2
je .next
dec ebx
shl ebx, 3
lea ebx, [ebx+ebx*4]
add ebx, [sec]
mov eax, [ebx+CFS.VirtualAddress]
add [edi+CSYM.Value], eax
.next:
add edi, CSYM_SIZE
mov [symbols], edi
dec [sym_count]
jnz .fix
mov eax, [retval]
ret
endp
align 4
proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword
locals
n_sec dd ?
endl
mov eax, [coff]
movzx ebx, [eax+CFH.nSections]
mov [n_sec], ebx
.fix_sec:
mov esi, [sec]
mov edi, [esi+CFS.PtrReloc]
add edi, [coff]
movzx ecx, [esi+CFS.NumReloc]
test ecx, ecx
jz .next
.next_reloc:
mov ebx, [edi+CRELOC.SymIndex]
add ebx,ebx
lea ebx,[ebx+ebx*8]
add ebx, [sym]
mov edx, [ebx+CSYM.Value]
cmp [edi+CRELOC.Type], 6
je .dir_32
cmp [edi+CRELOC.Type], 20
jne .next_reloc
.rel_32:
mov eax, [edi+CRELOC.VirtualAddress]
add eax, [esi+CFS.VirtualAddress]
sub edx, eax
sub edx, 4
jmp .fix
.dir_32:
mov eax, [edi+CRELOC.VirtualAddress]
add eax, [esi+CFS.VirtualAddress]
.fix:
add [eax], edx
add edi, 10
dec ecx
jnz .next_reloc
.next:
add [sec], COFF_SECTION_SIZE
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
align 4
proc load_driver stdcall, driver_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
start dd ?
exports dd ? ;fake exports table
dd ?
file_name rb 13+16+4+1 ; '/sys/drivers/<up-to-16-chars>.obj'
endl
lea edx, [file_name]
mov dword [edx], '/sys'
mov dword [edx+4], '/dri'
mov dword [edx+8], 'vers'
mov byte [edx+12], '/'
mov esi, [driver_name]
.redo:
lea edx, [file_name]
lea edi, [edx+13]
mov ecx, 16
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
mov dword [edi], '.obj'
mov byte [edi+4], 0
stdcall load_file, edx
mov [coff], eax
test eax, eax
jz .exit
movzx ebx, [eax+CFH.nSections]
lea edx, [eax+20]
xor ecx, ecx
@@:
add ecx, [edx+CFS.SizeOfRawData]
add ecx, 15
and ecx, not 15
add edx, COFF_SECTION_SIZE
dec ebx
jnz @B
mov [img_size], ecx
mov edx, PG_SW
call @mem_alloc@8
test eax, eax
mov [img_base], eax
jz .fail
mov [img_base], eax
mov edi, eax
xor eax, eax
mov ecx, [img_size]
add ecx, 4095
and ecx, not 4095
shr ecx, 2
cld
rep stosd
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+CFS.VirtualAddress], edi
mov esi, [eax+CFS.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+CFS.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15
and edi, not 15
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
mov ebx, [edx+CFH.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+CFH.nSymbols]
add ecx,ecx
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
lea ebx, [exports]
mov dword [ebx], kernel_export
mov dword [ebx+4], 0
lea eax, [edx+20]
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\
[strings], ebx
test eax, eax
jz .link_fail
mov ebx, [coff]
add ebx, 20
stdcall fix_coff_relocs, [coff], ebx, [sym]
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion
test eax, eax
jz .link_fail
mov eax, [eax]
shr eax, 16
cmp eax, DRV_COMPAT
jb .ver_fail
cmp eax, DRV_CURRENT
ja .ver_fail
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szSTART
mov [start], eax
mov ecx, [coff]
call @mem_free@4
mov ebx, [start]
stdcall ebx, DRV_ENTRY
test eax, eax
jnz .ok
mov ecx, [img_base]
call @mem_free@4
xor eax, eax
ret
.ok:
mov ebx, [img_base]
mov [eax+SRV.base], ebx
mov ecx, [start]
mov [eax+SRV.entry], ecx
ret
.ver_fail:
mov esi, msg_CR
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
mov esi, msg_version
call sys_msg_board_str
mov esi, msg_www
call sys_msg_board_str
jmp .cleanup
.link_fail:
mov esi, msg_module
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
.cleanup:
mov ecx, [img_base]
call @mem_free@4
.fail:
mov ecx, [coff]
call @mem_free@4
.exit:
xor eax, eax
ret
endp
align 4
proc load_library stdcall, file_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
exports dd ?
endl
cli
stdcall load_file, [file_name]
test eax, eax
jz .fail
mov [coff], eax
movzx ecx, [eax+CFH.nSections]
xor ebx, ebx
lea edx, [eax+20]
@@:
add ebx, [edx+CFS.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, COFF_SECTION_SIZE
dec ecx
jnz @B
mov [img_size], ebx
call init_heap
stdcall user_alloc, [img_size]
test eax, eax
jz .fail
mov [img_base], eax
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+CFS.VirtualAddress], edi
mov esi, [eax+CFS.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+CFS.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15 ;-new_app_base
and edi, -16
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
mov ebx, [edx+CFH.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+CFH.nSymbols]
add ecx,ecx
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
lea eax, [edx+20]
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\
[strings], dword 0
test eax, eax
jnz @F
@@:
mov edx, [coff]
; movzx ebx, [edx+CFH.nSections]
; xor edi, edi
; lea eax, [edx+20]
;@@:
; add [eax+CFS.VirtualAddress], edi ;patch user space offset
; add eax, COFF_SECTION_SIZE
; dec ebx
; jnz @B
add edx, 20
stdcall fix_coff_relocs, [coff], edx, [sym]
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS
mov [exports], eax
mov ecx, [coff]
call @mem_free@4
mov eax, [exports]
ret
.fail:
xor eax, eax
ret
endp
align 4
proc stop_all_services
mov edx, [srv.fd]
.next:
cmp edx, srv.fd-SRV_FD_OFFSET
je .done
cmp [edx+SRV.magic], ' SRV'
jne .next
cmp [edx+SRV.size], SRV_SIZE
jne .next
mov ebx, [edx+SRV.entry]
mov edx, [edx+SRV.fd]
test ebx, ebx
jz .next
push edx
stdcall ebx, dword -1
pop edx
jmp .next
.done:
ret
endp
; param
; eax= size
; ebx= pid
align 4
_CreateObject:
create_kernel_object:
push ebx
call malloc
pop ebx
test eax, eax
jz .fail
mov ecx,[current_slot]
add ecx, APP_OBJ_OFFSET
pushfd
cli
mov edx, [ecx+APPOBJ.fd]
mov [eax+APPOBJ.fd], edx
mov [eax+APPOBJ.bk], ecx
mov [eax+APPOBJ.pid], ebx
mov [ecx+APPOBJ.fd], eax
mov [edx+APPOBJ.bk], eax
popfd
.fail:
ret
; param
; eax= object
align 4
_DestroyObject:
destroy_kernel_object:
pushfd
cli
mov ebx, [eax+APPOBJ.fd]
mov ecx, [eax+APPOBJ.bk]
mov [ebx+APPOBJ.bk], ecx
mov [ecx+APPOBJ.fd], ebx
popfd
xor edx, edx ;clear common header
mov [eax], edx
mov [eax+4], edx
mov [eax+8], edx
mov [eax+12], edx
mov [eax+16], edx
call free ;release object memory
ret
if 0
irq:
.irq0:
pusfd
pushad
push IRQ_0
jmp .master
.irq_1:
pusfd
pushad
push IRQ_1
jmp .master
.master:
mov ax, app_data
mov ds, eax
mov es, eax
mov ebx, [esp+4] ;IRQ_xx
mov eax, [irq_handlers+ebx+4]
call intr_handler
mov ecx, [esp+4]
cmp [irq_actids+ecx*4], 0
je @F
in al, 0x21
bts eax, ecx
out 0x21, al
mov al, 0x20
out 0x20, al
jmp .restart
.slave:
mov ax, app_data
mov ds, eax
mov es, eax
mov ebx, [esp+4] ;IRQ_xx
mov eax, [irq_handlers+ebx+4]
call intr_handler
mov ecx, [esp+4]
sub ecx, 8
cmp [irq_actids+ecx*4], 0
je @F
in al, 0xA1
bts eax, ecx
out 0xA1, al
mov al, 0x20
out 0xA0, al
out 0x20, al
.restart:
mov ebx, [next_slot]
test ebx, ebx
jz @F
mov [next_task],0
mov esi, [prev_slot]
call do_change_task
add esp, 4
iretd
end if