< -->

;scrsvr.asm
;Пример простой задачи, реализующей нитевую многозадачность в DOS
	.model tiny
	.code
	.386
	org 100h
start:
	mov	ax, 1600h
	int	2Fh
	test	al, al
	jz	no_windows
	mov	ax, 1827h
	mov	bx, offset message_err
	mov	cx, message_length/2
unxor:
	xor	word ptr [bx], ax
	inc	bx
	inc	bx
	loop	unxor
	mov	ah, 9
	mov	dx, offset message_err
	int	21h
	jmp	exit_prg
no_windows:
	mov ax, 13h
	int 10h

	call init_threads
	mov bx, 1
	
	push bp
	mov bp, sp

	push 1
x_inc	equ	word ptr [bp-2]
	push 0
y_inc	equ	word ptr [bp-4]
	push 128-4
coords_head	equ	word ptr [bp-6]
	push 0
coords_tail	equ	word ptr [bp-8]
	sub sp, 64*2

	mov di, sp
	mov cx, 64
	mov ax, 10
	push ds
	pop es
	rep stosw
line_coords	equ	word ptr [bp-(64*2)-8]
	push 0A000h
	pop es
main_loop:
	call display_line

	push bx
	mov ebx, 50
	call z_random
	mov ax, word ptr x_inc
	mov bx, word ptr y_inc
	test dx, dx
	jz rot_right
	dec dx
	jnz exit_rot

	neg ax
	xchg ax, bx
	jmp short exit_rot
rot_right:
	neg bx
	xchg ax, bx
exit_rot:
	mov word ptr x_inc, ax
	mov word ptr y_inc, bx
	pop bx

	mov di, word ptr coords_head
	mov cx, word ptr line_coords[di]
	mov dx, word ptr line_coords[di+2]
	add cx, word ptr y_inc
	add dx, word ptr x_inc
	add di, 4
	and di, 127
	mov word ptr coords_head, di
	mov word ptr line_coords[di], cx
	mov word ptr line_coords[di+2], dx
	mov di, word ptr coords_tail
	add di, 4
	and di, 127
	mov word ptr coords_tail, di
	mov cx, -1
	loop $
	mov cx, -1
	loop $
	mov cx, -1
	loop $

	mov ah, 1
	int 16h
	jz main_loop
	mov ah, 0
	int 16h
	leave
	call shutdown_threads
	mov ax, 3
	int 10h
exit_prg:
	int 20h

putpixel proc near
	push di
	lea ecx, [ecx*4+ecx]
	shl cx, 6
	add dx, cx
	mov di, dx
	mov al, bl
	stosb
	pop di
	ret
putpixel endp

display_line proc near
	mov di, word ptr coords_tail
continue_line_display:
	cmp di, word ptr coords_head
	je line_displayed
	call display_point
	add di, 4
	and di, 127
	jmp short continue_line_display
line_displayed:
	call display_point
	mov di, word ptr coords_tail
	push bx
	mov bx, 0
	call display_point
	pop bx
	ret
display_line endp

display_point proc near
	mov cx, word ptr line_coords[di]
	mov dx, word ptr line_coords[di+2]
	call putpixel
	ret
display_point endp

z_random:
	push ebx
	cmp byte ptr zr_init_flag, 0
	je zr_init
	mov eax, zr_prev_rand
zr_cont:
	mul dword ptr rnd_number
	div dword ptr rnd_number2
	mov zr_prev_rand, edx
	pop ebx
	mov eax, edx
	xor edx, edx
	div ebx
	ret
zr_init:
	push 0040h
	pop fs
	mov eax, fs:[006Ch]
	mov zr_prev_rand, eax
	mov byte ptr zr_init_flag, 1
	jmp zr_cont			; ? short ?
rnd_number	dd	16807
rnd_number2	dd	2147483647
zr_init_flag	db	0                ; ? поменять местами?
zr_prev_rand	dd	0

; Код диспетчера

thread_struc struc
_ax	dw	?
_bx	dw	?
_cx	dw	?
_dx	dw	?
_si	dw	?
_di	dw	?
_bp	dw	?
_sp	dw	?
_ip	dw	?
_flags	dw	?
thread_struc ends

init_threads proc near
	pushf
	pusha
	push es
	mov ax, 3508h
	int 21h
	mov word ptr old_int08h, bx
	mov word ptr old_int08h+2, es
	mov ax, 2508h
	mov dx, offset int08h_handler
	int 21h
	pop es
	popa
	popf

	mov thread1._ax, ax
	mov thread2._ax, ax
	mov thread1._bx, bx
	mov thread2._bx, bx
	mov thread1._cx, cx
	mov thread2._cx, cx
	mov thread1._dx, dx
	mov thread2._dx, dx
	mov thread1._si, si
	mov thread2._si, si
	mov thread1._di, di
	mov thread2._di, di
	mov thread1._bp, bp
	mov thread2._bp, bp
	mov thread1._sp, offset thread1_stack+512
	mov thread2._sp, offset thread2_stack+512
	pop ax
	mov thread1._ip, ax
	mov thread2._ip, ax
	pushf
	pop ax
	mov thread1._flags, ax
	mov thread2._flags, ax
	mov sp, thread1._sp
	jmp word ptr thread1._ip
init_threads endp

current_thread db 1

int08h_handler proc far
	pushf
		db	9Ah
old_int08h	dd	0

	mov save_di, di
	mov save_si, si
	pushf
	cmp byte ptr current_thread, 1
	je thread1_to_thread2
	mov byte ptr current_thread, 1
	mov si, offset thread1
	mov di, offset thread2
	jmp short order_selected
thread1_to_thread2:
	mov byte ptr current_thread, 2
	mov si, offset thread2
	mov di, offset thread1
order_selected:
	mov ax, [si]._si
	push save_si
	pop [di]._si
	mov save_si, ax
	mov ax, [si]._di
	push save_di
	pop [di]._di
	mov save_di, ax

	mov [di._ax], ax
	mov ax, [si._ax]
	mov [di._bx], bx
	mov bx, [si._bx]
	mov [di._cx], cx
	mov cx, [si._cx]
	mov [di._dx], dx
	mov dx, [si._dx]
	mov [di._bp], bp
	mov bp, [si._bp]

	pop [di._flags]
	push [si._flags]
	popf
	pop [di._ip]
	add sp, 4
	mov [di._sp], sp
	mov sp, [si._sp]
	push [si._ip]
	mov di, save_di
	mov si, save_si
	retn
called_far:
	popf
	pop bx
	pop ax
	mov bp, save_di
	iret
int08h_handler endp

save_di	dw	?
save_si	dw	?

shutdown_threads proc near
	mov ax, 2508h
	lds dx, dword ptr old_int08h
	int 21h
	ret
shutdown_threads endp

message_err 	db	"еµПґЗµПЅ8єъЗ8И°Й»ЗёЛґЗ8ЗёЖ¶ЕёВъъЙіЛІЙ8Е8cWt8ЗЅБ°ЛЅ8"
		db	"µВ8Пї·ЙјOHoPyPk6$"
message_length = $ - message_err
;	"Внимание! Эта программа работает только в DOS режиме! "
;	"(не из под Wowwaws)." x XOR 27h 18h

thread1	thread_struc <>
thread2	thread_struc <>
thread1_stack db 512 dup (?)
thread2_stack db 512 dup (?)
end	start

Назад