📄 tskdos.asm
字号:
push ax
push ax
mov ax,offset _critical
push ds
push ax
call _asm_wait_flag_clear
add sp,8
;
no_crit:
mov cs:ctask_active,1 ; mark that we are active
sti ; Interrupts allowed now
;
cmp ah,4ch ; terminate?
jne dosent_x
mov ah,0 ; translate to fn 0
dosent_x:
cmp ah,0ch
jbe lower_funcs
jmp upper_funcs
;
; Functions 00-0C
;
lower_funcs:
;
; first, request the "lower_dos" resource
;
mov bx,offset _lower_dos
xor cx,cx
push cx ; no timeout
push cx
push ds ; resource address
push bx
call _asm_request_resource
add sp,8
;
; we have it, now let's get the upper_dos resource, too
;
mov bx,offset _upper_dos
xor cx,cx
push cx ; no timeout
push cx
push ds ; resource address
push bx
call _asm_request_resource
add sp,8
;
; both resources gained, now we may execute the function if dos is free
;
pop di
pop si
pop ax
pop bx
pop cx
pop dx
;
call wait_dos_free
;
or ah,ah ; terminate ?
je fg_terminate ; special treatment required
cmp ah,4ch
je fg_terminate ; special treatment required
pop ds
pop es
popf
pop bp
;
dos ; execute function
;
; Now we have to release the resources.
;
pushf ; save registers again
sti
push es
push ds
push dx
push cx
push bx
push ax
push si
push di
;
mov bx,SEG dgroup
mov ds,bx
mov es,bx
;
mov bx,offset _upper_dos
push ds ; resource address
push bx
call _asm_release_resource
add sp,4
;
mov bx,offset _lower_dos
push ds ; resource address
push bx
call _asm_release_resource
add sp,4
;
; If both resources are free now, clear the ctask_active flag to
; allow other background processes to gain access to DOS.
;
cli
mov ax,_upper_dos.rstate
or ax,ax
jz no_relc
cmp ax,_lower_dos.rstate
jne no_relc
mov cs:ctask_active,0
no_relc:
;
; All done, restore registers and return.
;
pop di
pop si
pop ax
pop bx
pop cx
pop dx
pop ds
pop es
popf
;
ret 2 ; don't restore flags
;
;
; The terminate request requires special treatment.
; Since terminating the program without first un-installing
; would crash the system, we do this here, not without telling
; the user something went very wrong.
;
fg_terminate:
cli
call _asm_remove_tasker
mov dx,offset term_err_msg
mov ah,9
int 21h
mov ax,4cffh
int 21h
;
;--------------------------------------------------------------------------
;
; Functions 0D and above
;
upper_funcs:
mov bx,offset _upper_dos
xor cx,cx
push cx ; no timeout
push cx
push ds ; resource address
push bx
call _asm_request_resource
add sp,8
;
; resource gained, now we may execute the function if dos is free
;
pop di
pop si
pop ax
pop bx
pop cx
pop dx
;
call wait_dos_free
;
pop ds
pop es
;
;
; Filter pseudo-functions C0/C1 (Absolute Read/Write)
;
cmp ah,0c0h
jne uf_exec1
popf
pop bp
call exec_absread
jmp short uf_complete
uf_exec1:
cmp ah,0c1h
jne uf_exec2
popf
pop bp
call exec_abswrite
jmp short uf_complete
;
uf_exec2:
popf
pop bp
dos ; execute function
;
; Now we have to release the resources.
;
uf_complete:
pushf ; save registers again
sti
push es
push ds
push dx
push cx
push bx
push ax
push si
push di
;
mov bx,SEG dgroup
mov ds,bx
mov es,bx
;
mov bx,offset _upper_dos
push ds ; resource address
push bx
call _asm_release_resource
add sp,4
;
; If both resources are free now, clear the ctask_active flag to
; allow other background processes to gain access to DOS.
;
cli
mov ax,_upper_dos.rstate
or ax,ax
jz no_relc1
cmp ax,_lower_dos.rstate
jne no_relc1
mov cs:ctask_active,0
no_relc1:
;
; All done, restore registers and return.
;
pop di
pop si
pop ax
pop bx
pop cx
pop dx
pop ds
pop es
popf
;
ret 2 ; don't restore flags
;
;
dosentry endp
;
;--------------------------------------------------------------------------
;
; Absolute Read/Absolute Write.
;
exec_absread proc near
pushf
call cs:savabsread
inc sp ; Remove flags (not using ADD,
inc sp ; this would clobber Carry)
ret
exec_absread endp
;
exec_abswrite proc near
pushf
call cs:savabswrite
inc sp ; Remove flags (not using ADD,
inc sp ; this would clobber Carry)
ret
exec_abswrite endp
;
;----------------------------------------------------------------------------
;
wait_dos_free proc near
;
push es
push bx
in_use_loop:
cmp idle_active,0 ; idle interrupt active?
jne dos_free ; then don't check for flag
;
les bx,in_use
cmp byte ptr es:[bx],0
jne is_in_use
cmp dos310,0
je dos_free
les bx,in_error
cmp byte ptr es:[bx],0
je dos_free
is_in_use:
pushf
call scheduler
jmp in_use_loop
;
dos_free:
pop bx
pop es
ret
;
wait_dos_free endp
;
;----------------------------------------------------------------------------
;
; INT 28: DOS Idle Interrupt
;
idleentry proc far
;
push ds
push es
push ax
;
mov ax,SEG dgroup
mov ds,ax
mov es,ax
;
; Check if someone is waiting for upper_dos. If not, we can return
; immediately.
;
mov ax,word ptr _upper_dos.rwaiting
or ax,word ptr _upper_dos.rwaiting+2
jz idle_exit
;
; Also make sure this is not a second invocation of INT 28.
; Normally, this should never happen, but better safe than sorry.
;
cmp idle_active,0
jne idle_exit
inc idle_active
;
; someone is waiting, let's please him by releasing the resource
;
mov idle_ss,ss ; Switch to local stack
mov idle_sp,sp
mov ax,ds
mov ss,ax
mov sp,offset local_stack
;
sti ; Interrupts allowed now
;
push bx ; save remaining regs
push cx
push dx
;
; temporarily increase priority
;
les bx,_tsk_current
push es:prior[bx]
mov es:prior[bx],0ffffh
push bx
push es
;
; release resource & request it again
;
mov ax,ds
mov es,ax
mov bx,offset _upper_dos
push ds
push bx
call _asm_release_resource
add sp,4
;
mov bx,offset _upper_dos
xor cx,cx
push cx
push cx
push ds
push bx
call _asm_request_resource
add sp,8
;
; ready, restore priority, stack & regs
;
cli
pop es
pop bx
pop es:prior[bx]
;
pop dx
pop cx
pop bx
;
mov ss,idle_ss ; restore stack
mov sp,idle_sp
;
mov idle_active,0
;
idle_exit:
pop ax
pop es
pop ds
;
jmp cs:savidle ; chain to original interrupt
;
idleentry endp
;
;---------------------------------------------------------------------------
;
; INT 2A: DOS Critical Section Interrupt.
;
; Not documented.
; Is used by DOS PRINT to mark Critical Regions.
; Usage by PRINT:
; AX = 8700 - Begin Critical Region
; Returns:
; Carry set if already active.
; AX = 8701 - End Critical Region
;
; Both these functions are handled here.
;
; Other usage in DOS, function unknown:
; AH = 82 (AL undefined)
; seems to be called on DOS-Functions > 0C
; AH = 84 (AL undefined)
; seems to be called when DOS is idle
;
; These functions are currently ignored.
;
critsectint proc far
cmp ax,8700h ; Enter critical region
jne csi1
cmp cs:critsect_active,0
stc
jnz critsect_end
cmp cs:ctask_active,0
stc
jnz critsect_end
;
inc cs:critsect_active
push ax
push bx
push cx
push dx
push ds
push es
mov ax,seg dgroup
mov ds,ax
mov es,ax
mov ax,word ptr _tsk_current
mov word ptr cs:crit_task,ax
mov ax,word ptr _tsk_current+2
mov word ptr cs:crit_task+2,ax
mov ax,offset _critical
push ds
push ax
call _asm_set_flag
add sp,4
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
clc
critsect_end:
ret 2
;
csi1:
cmp ax,8701h ; Leave critical region
jne csi2
mov cs:critsect_active,0
push ax
push bx
push cx
push dx
push ds
push es
mov ax,seg dgroup
mov ds,ax
mov es,ax
mov ax,offset _critical
push ds
push ax
call _asm_clear_flag
add sp,4
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
csi2:
iret
;
critsectint endp
;
;
;---------------------------------------------------------------------------
;
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -