; млллллллм   мллллллллм  млллллллм
;оллллп  пп   плллммм пп олллл  пллн
;олллн лпллл      пплллм  ллллппллм
;оллллм мллл олллм  мллл олллл  мллл
; плллллллпл  пллллллллп  плллллллп

			;NASM-IDE ASM Assistant Assembler Project File
[BITS 16]               ;Set code generation to 16 bit mode
[ORG 0x0100]            ;Set code start address to 0100h


[SEGMENT .text]         ;Main code segment
;;; Reserve processes stack
	;; save the stack
	mov	[Stack_Main], sp
	
	;; Process 1:
	mov	sp, Stack_Area_P1+511; sp is now the P1 stack
  	pushf			; save flags
	push	cs		; save cs
  	mov	ax, PROCESS_1
  	push	ax		; PROCESS_1 to stack
  	pusha
	pushf
	push	es
	push	ds
	mov	[Stack_P1], sp
	or	[Processes], word 00001b; P1 is active
	mov	ax, 0101h
	call	PrintProcessStatus
	
	;; Process 2:
	mov	sp, Stack_Area_P2+511; sp is now the P2 stack
  	pushf			; save flags
	push	cs		; save cs
  	mov	ax, PROCESS_2
  	push	ax		; PROCESS_2 to stack
  	pusha
	pushf
	push	es
	push	ds
	mov	[Stack_P2], sp
	or	[Processes], word 00010b; P2 is active
	mov	ax, 0102h
	call	PrintProcessStatus

	;; Process 3:
	mov	sp, Stack_Area_P3+511; sp is now the P3 stack
  	pushf			; save flags
	push	cs		; save cs
  	mov	ax, PROCESS_3
  	push	ax		; PROCESS_3 to stack
  	pusha
	pushf
	push	es
	push	ds
	mov	[Stack_P3], sp
	or	[Processes], word 00100b; P3 is active
	mov	ax, 0103h
	call	PrintProcessStatus
		
	;; Process 4:
	mov	sp, Stack_Area_P4+511; sp is now the P4 stack
  	pushf			; save flags
	push	cs		; save cs
  	mov	ax, PROCESS_4
  	push	ax		; PROCESS_4 to stack
  	pusha
	pushf
	push	es
	push	ds
	mov	[Stack_P4], sp
	or	[Processes], word 01000b; P4 is active
	mov	ax, 0104h
	call	PrintProcessStatus

	;; Process 5:
	mov	sp, Stack_Area_P5+511; sp is now the P5 stack
  	pushf			; save flags
	push	cs		; save cs
  	mov	ax, PROCESS_5
  	push	ax		; PROCESS_5 to stack
  	pusha
	pushf
	push	es
	push	ds
	mov	[Stack_P5], sp
	or	[Processes], word 10000b; P5 is active
	
				
;;; Assign to ints
 	call	AssignIntFunction
	;; starts with process 1
  	mov	ax, [Stack_P1]
  	mov	sp, ax
  	mov	[Process], word 1; process 1 is running
  	jmp	PROCESS_1	; go to process 1

	



	

;;; AssignIntFunction: Assigns SCHEDULER as Clock int
; Parameters:
;   - None
; Return
;   - None
AssignIntFunction:
	; save parameters we will use
	pusha
	cli			; no interrupts by now
	les	di, [IntSegment]	; es = interruption segment
	;; Clock
	;; Save actual interruption value
	mov	dx, [es:8h*4]
	mov	cx, [es:8h*4+2]
	mov	[es:60h*4], dx
	mov	[es:60h*4+2], cx
	;; Assign new values
	mov	ax, cs
	mov	bx, SCHEDULER
	mov	[es:8h*4], bx
	mov	[es:8h*4+2], ax
	
	sti			; now interrupts are available again
	; restore parameters we will use
	popa
	ret

	
	
;;; RestoreIntFunction:	restore the previous assigned interruption
; Parameters:
;   - None
; Return
;   - None
RestoreIntFunction:
	;; save values
	pusha
	cli			; no ints
	les	di, [IntSegment]	; es = interruption segment
	;; Clock
	;; retore interrupt
	xor	ax, ax
	mov	es, ax
	mov	dx, [es:60h*4]
	mov	cx, [es:60h*4+2]	
	mov	[es:8h*4], dx
	mov	[es:8h*4+2], cx	
	sti			; ints agains
	;; restore values
	popa
	ret



	
;;; SCHEDULER: manage 4 processes runnig at the same time
; Parameters:
;   - None
; Return
;   - None
SCHEDULER:
	int	60h		; call interruption
	;; save values
	pusha
	pushf
	push	es
	push	ds
	
SCHEDULER_SaveStack:
	cmp	word [cs:Process], 00001b
	je	SCHEDULER_SaveStack_P1
	cmp	word [cs:Process], 00010b
	je	SCHEDULER_SaveStack_P2
	cmp	word [cs:Process], 00100b
	je	SCHEDULER_SaveStack_P3
	cmp	word [cs:Process], 01000b
	je	SCHEDULER_SaveStack_P4
	cmp	word [cs:Process], 10000b
	je	SCHEDULER_SaveStack_P5
	jmp	SCHEDULER_END_SaveStack; shouln't occur, but...
SCHEDULER_SaveStack_P1:
	mov	[cs:Stack_P1], sp
	jmp	SCHEDULER_END_SaveStack
SCHEDULER_SaveStack_P2:
	mov	[cs:Stack_P2], sp
	jmp	SCHEDULER_END_SaveStack
SCHEDULER_SaveStack_P3:
	mov	[cs:Stack_P3], sp
	jmp	SCHEDULER_END_SaveStack
SCHEDULER_SaveStack_P4:
	mov	[cs:Stack_P4], sp
	jmp	SCHEDULER_END_SaveStack
SCHEDULER_SaveStack_P5:
	mov	[cs:Stack_P5], sp
	jmp	SCHEDULER_END_SaveStack
SCHEDULER_END_SaveStack:

SCHEDULER_ChangeStack:
	cmp	word [cs:Process], 10000b
	jge	SCHEDULER_Restart
	mov	ax, [cs:Process]
	shl	ax,1
	mov	[cs:Process], ax
	jmp	SCHEDULER_NewProcess
SCHEDULER_Restart:	
	mov	word [cs:Process], 1
SCHEDULER_NewProcess:
SCHEDULER_NewProcess_P1:
	cmp	word [cs:Process], 00001b
	jne	SCHEDULER_NewProcess_P2
	mov	ax, [cs:Processes]
	or	ax, 11110b
	cmp	ax, 11111b
	je	SCHEDULER_ChangeStack_P1
	jne	SCHEDULER_ChangeStack; back and try again
SCHEDULER_NewProcess_P2:
	cmp	word [cs:Process], 00010b
	jne	SCHEDULER_NewProcess_P3
	mov	ax, [cs:Processes]
	or	ax, 11101b
	cmp	ax, 11111b
	je	SCHEDULER_ChangeStack_P2
	jne	SCHEDULER_ChangeStack; back and try again
SCHEDULER_NewProcess_P3:
	cmp	word [cs:Process], 00100b
	jne	SCHEDULER_NewProcess_P4
	mov	ax, [cs:Processes]
	or	ax, 11011b
	cmp	ax, 11111b
	je	SCHEDULER_ChangeStack_P3
	jne	SCHEDULER_ChangeStack; back and try again
SCHEDULER_NewProcess_P4:
	cmp	word [cs:Process], 01000b
	jne	SCHEDULER_NewProcess_P5
	mov	ax, [cs:Processes]
	or	ax, 10111b
	cmp	ax, 11111b
	je	SCHEDULER_ChangeStack_P4
	jne	SCHEDULER_ChangeStack; back and try again
SCHEDULER_NewProcess_P5:
	;; always run Process 5
	jmp	SCHEDULER_ChangeStack_P5
SCHEDULER_ChangeStack_P1:
	mov	sp, [cs:Stack_P1]
	mov	word [cs:Process], 00001b
	jmp	SCHEDULER_END_ChangeStack
SCHEDULER_ChangeStack_P2:
	mov	sp, [cs:Stack_P2]
	mov	word [cs:Process], 00010b
	jmp	SCHEDULER_END_ChangeStack
SCHEDULER_ChangeStack_P3:
	mov	sp, [cs:Stack_P3]
	mov	word [cs:Process], 00100b
	jmp	SCHEDULER_END_ChangeStack
SCHEDULER_ChangeStack_P4:
	mov	sp, [cs:Stack_P4]
	mov	word [cs:Process], 01000b
	jmp	SCHEDULER_END_ChangeStack
SCHEDULER_ChangeStack_P5:
	mov	sp, [cs:Stack_P5]
	mov	word [cs:Process], 10000b
	jmp	SCHEDULER_END_ChangeStack
SCHEDULER_END_ChangeStack:		
SCHEDULER_END:	

	;; restore values
	pop	ds
	pop	es
	popf
	popa
	iret		
	


	

	
	
	
	
		
;;; PROCESS_1:	print some text on the top of the screen
PROCESS_1:	
	mov	si, STR_PROC_1	
	mov	ax, cs
	mov	ds, ax
		
	les	di, [cs:VideoSegment]
	mov	ah, 1Fh
	mov	al, ' '
	;; clear the screen
	push	bx
	xor	bx, bx
PROCESS_1_Loop1:
	inc	bx
	stosw
	cmp	bx, 12*80	; 12 linhas de 80 colunas
	jne	PROCESS_1_Loop1
	;; screen cleaned.

	;; Enter the main loop (infinite loop)
	pop	bx
	xor	di, di	
	xor	cx, cx
PROCESS_1_Loop_Main:
PROCESS_1_Loop2:
	;; load char from string and print on the screen
	lodsb
	cmp	al, 0
	je	PROCESS_1_Loop2_NOPRINT
	stosw
	inc	cx
PROCESS_1_Loop2_NOPRINT:
	;; wait some ticks
  	push	cx
  	push	dx
	xor	cx, cx
PROCESS_1_Loop3:
	inc	cx
	xor	dx, dx
PROCESS_1_Loop4:
	inc	dx
	cmp	dx, 65535
	jne	PROCESS_1_Loop4
	cmp	cx, 100
	jne	PROCESS_1_Loop3
	;; end of the wait loop
  	pop	dx
  	pop	cx

	cmp	cx, 12*80
	jl	PROCESS_1_Loop_Main_Cont
	xor	di, di
	xor	cx, cx
PROCESS_1_Loop_Main_Cont:
	;; we reach the end of the string?
	cmp	al, 0
	jne	PROCESS_1_Loop2
	;; reset to the begining of the string, change the color
	mov	si, STR_PROC_1
	cmp	ah, 1Fh
	je	PROCESS_1_Color_2
PROCESS_1_Color_1:
	mov	ah, 1Fh
	jmp	PROCESS_1_Color_Cont
PROCESS_1_Color_2:
	mov	ah, 17h
	jmp	PROCESS_1_Color_Cont
PROCESS_1_Color_Cont:
	jmp	PROCESS_1_Loop_Main;  the loop that never finnishes!
	







	
;;; PROCESS_2:	print some text on the center-left of the screen
PROCESS_2:
	mov	si, STR_PROC_2
	mov	ax, cs
	mov	ds, ax
		
	les	di, [cs:VideoSegment]
	mov	di, 12*80*2	; go to start position
	mov	ah, 2Fh
	mov	al, ' '
	;; clear the screen
	push	bx
	push	cx
	xor	bx, bx	
PROCESS_2_Loop1_1:
	inc	bx
	xor	cx, cx
PROCESS_2_Loop1_2:
	inc	cx
	stosw
	cmp	cx, 40		; 40 columns
	jl	PROCESS_2_Loop1_2
	add	di, 40*2	; add 40 rows (2 bytes per row) 
	cmp	bx, 12		; 12 rows
	jl	PROCESS_2_Loop1_1
	;; screen cleaned.

	;; Enter the main loop (infinite loop)
	pop	cx
	pop	bx
	les	di, [cs:VideoSegment]
	mov	di, 12*80*2	; go to start position
	xor	cx, cx
	xor	bx, bx
PROCESS_2_Loop_Main:
PROCESS_2_Loop2:
	;; load char from string and print on the screen
	lodsb
	cmp	al, 0
	je	PROCESS_2_Loop2_NOPRINT
	stosw
	inc	cx
	inc	bx
PROCESS_2_Loop2_NOPRINT:
	;; wait some ticks
  	push	cx
  	push	dx		
	xor	cx, cx
PROCESS_2_Loop3:
	inc	cx
	xor	dx, dx
PROCESS_2_Loop4:
	inc	dx
	cmp	dx, 65535
	jne	PROCESS_2_Loop4
	cmp	cx, 1
	jne	PROCESS_2_Loop3
	;; end of the wait loop
  	pop	dx
  	pop	cx

	cmp	bx, 40
	jl	PROCESS_2_Loop_Main_Cont1
	xor	bx, bx
	add	di, 40*2

PROCESS_2_Loop_Main_Cont1:	
	cmp	cx, 12*40
	jl	PROCESS_2_Loop_Main_Cont2
	mov	di, 12*80*2	; go to start position
	xor	cx, cx
PROCESS_2_Loop_Main_Cont2:
	
	;; we reach the end of the string?
	cmp	al, 0
	jne	PROCESS_2_Loop2
	;; reset to the begining of the string, change the color
	mov	si, STR_PROC_2
	cmp	ah, 2Fh
	je	PROCESS_2_Color_2
PROCESS_2_Color_1:
	mov	ah, 2Fh
	jmp	PROCESS_2_Color_Cont
PROCESS_2_Color_2:
	mov	ah, 57h
	jmp	PROCESS_2_Color_Cont
PROCESS_2_Color_Cont:
	jmp	PROCESS_2_Loop_Main;  the loop that never finnishes!

	
	
	
;;; PROCESS_3:	print some text on the center-left of the screen
PROCESS_3:
	lds	si, [cs:VideoSegment]; read from ds:si
	les	di, [cs:VideoSegment]; write to es:di

	mov	si, 80*2*12	; start reading from 12,0
	mov	di, 80*2*12+79*2; start writing to 12,79 (and dec)

	xor	dx, dx
PROCESS_3_Loop1:
	inc	dx
	xor	cx, cx
PROCESS_3_Loop2:
	inc	cx
	;; read and write from video memory
	lodsw
	mov	[es:di], ax
	dec	di
	dec	di
	
	cmp	cx, 40
	jl	PROCESS_3_Loop2
	;; end of column loop
	add	si, 40*2
	add	di, 80*2+40*2
	
	cmp	dx, 12
	jl	PROCESS_3_Loop1	
	;; end of line loop
	jmp	PROCESS_3
	

PROCESS_4:
	;; Activates the PC Speaker
	push	ax
      	in	al, 61h		; get data from 61h
	or	al, 11b		; set bits 0 and 1
	out	61h, al		; send data to 61h
	;; Activates the PC Speaker Controller
	mov	ax, 0b6h
	out	43h, ax
	pop	ax
	
	cmp	ax, 1026
	je	PROCESS_4_Sound2
PROCESS_4_Sound1:
	mov	ax, 1026
	jmp	PROCESS_4_END_Sound
PROCESS_4_Sound2:
	mov	ax, 2274
PROCESS_4_END_Sound:	
	
	out	42h, al		; -play the sound
	xchg	ah, al		; -
	out	42h, al		; -
	xchg	ah, al
	
	;; wait
	xor	cx, cx
PROCESS_4_Loop1:
	inc	cx
	xor	dx, dx
PROCESS_4_Loop2:
	inc	dx
	cmp	dx, 65535
	jne	PROCESS_4_Loop2
	cmp	cx, 10
	jne	PROCESS_4_Loop1
	;; end of wait loop
	;; Closes the PC Speaker Controler
	push	ax
	in	al, 61h		; get data from 61h
	and	al, 00b		; unset bits 0 and 1
	out	61h, al		; send data to 61h
	pop	ax
	jmp	PROCESS_4

PROCESS_5:
PROCESS_5_WaitKey:
	mov	ah, 1
	int	16h
	jz	PROCESS_5_WaitKey
	;; read key
	mov	ah, 0
	int	16h

	;; will be used after, DO NOT CHANGE BX, CX until PROCESS_5_Toggle_*
	mov	bx, [cs:Processes]
	mov	cx, bx	
		
	cmp	al, '1'
	je	PROCESS_5_Toggle_P1
  	cmp	al, '2'
  	je	PROCESS_5_Toggle_P2
  	cmp	al, '3'
  	je	PROCESS_5_Toggle_P3
  	cmp	al, '4'
  	je	PROCESS_5_Toggle_P4
	cmp	al, 27		; ESC
	jne	PROCESS_5_NoQuit
	call	Quit
PROCESS_5_NoQuit:	

	
	jmp	PROCESS_5_END_Toggle	
PROCESS_5_Toggle_P1:
	or	cx, 11110b
	cmp	cx, 11111b
	jne	PROCESS_5_Toggle_P1_On
PROCESS_5_Toggle_P1_Off:
	mov	ax, 0001h
	call	PrintProcessStatus
	and	bx, 11110b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P1_On:
	mov	ax, 0101h
	call	PrintProcessStatus
	or	bx, 00001b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P2:
	or	cx, 11101b
	cmp	cx, 11111b
	jne	PROCESS_5_Toggle_P2_On
PROCESS_5_Toggle_P2_Off:
	mov	ax, 0002h
	call	PrintProcessStatus
	and	bx, 11101b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P2_On:
	mov	ax, 0102h
	call	PrintProcessStatus
	or	bx, 00010b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P3:
	or	cx, 11011b
	cmp	cx, 11111b
	jne	PROCESS_5_Toggle_P3_On
PROCESS_5_Toggle_P3_Off:
	mov	ax, 0003h
	call	PrintProcessStatus
	and	bx, 11011b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P3_On:
	mov	ax, 0103h
	call	PrintProcessStatus
	or	bx, 00100b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P4:
	or	cx, 10111b
	cmp	cx, 11111b
	jne	PROCESS_5_Toggle_P4_On
PROCESS_5_Toggle_P4_Off:
	mov	ax, 0004h
	call	PrintProcessStatus
	and	bx, 10111b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_Toggle_P4_On:
	mov	ax, 0104h
	call	PrintProcessStatus	
	or	bx, 01000b
	jmp	PROCESS_5_END_Toggle
PROCESS_5_END_Toggle:
	mov	[cs:Processes], bx
	jmp	PROCESS_5

Quit:
	;; Restore ints
 	call	RestoreIntFunction
	mov	sp, [Stack_Main]

	;; clear the screen
	mov     ah, 07h         ; ah = bg | fg
	mov     al, ' '         ; al = char
	; Let es be the Video Segment
	les     di, [cs:VideoSegment]  ; video memory address: es = b800, di = 0000
	
	xor     bx, bx
	; Main loop ( while (bx < screen_size) )        
Loop_FillScreen:
	mov     [es:bx], ax
	add     bx, 2
	cmp     bx, 4000
	jne     Loop_FillScreen

	
	
	ret
	
	

;;; PrintProcessStatus:	print the process <al> status in the last line
; Parameters:
;   al:	process number
;   ah:	process status:	 1=Running, 0=Paused
; Return:
;   none
PrintProcessStatus:
	push	es
	push	ds
	pusha

	les	di, [cs:VideoSegment]
	mov	cx, cs
	mov	ds, cx		; read from cs:si	
	
	push	ax
	;; set position in screen
	mov	di, 80*2*24
	mov	dl, al
	sub	dl, 1
	mov	al, 20*2
	mul	dl
	xor	ah, ah
	add	di, ax
	pop	ax
	
	cmp	ah, 1
	je	PrintProcessStatus_Choose_Running
PrintProcessStatus_Choose_Paused:
	mov	si, STR_PROC_5_PAU
	mov	dh, 04h		; red
	jmp	PrintProcessStatus_END_Choose
PrintProcessStatus_Choose_Running:
	mov	si, STR_PROC_5_RUN
	mov	dh, 02h		; red
	jmp	PrintProcessStatus_END_Choose
PrintProcessStatus_END_Choose:

	mov	dl, al
	add	dl, '0'
	mov	ax, dx
	mov	ah, 0Fh
	stosw
	mov	al, ':'
	stosw
	mov	ah, dh
		
PrintProcessStatus_Loop1:
	lodsb
	cmp	al, 0
	je	PrintProcessStatus_END_Loop1
	stosw
	jmp	PrintProcessStatus_Loop1
PrintProcessStatus_END_Loop1:
		
	popa
	pop	ds
	pop	es
	ret
		
	
	
	
	
[SEGMENT .data]         ;Initialised data segment
	VideoSegment    DD      0B8000000h; Video memory segment
	IntSegment	DD	000000000h; Interrupts segment
	Process		DW	00000; 
	Processes	DW	0000;
	Stack_Main	DW	0; stack pointer
	Stack_P1	DW	0; process 1 stack pointer
	Stack_P2	DW	0; process 2 stack pointer
	Stack_P3	DW	0; process 3 stack pointer
	Stack_P4	DW	0; process 4 stack pointer
	Stack_P5	DW	0; process 5 stack pointer
	STR_PROC_1	DB      "Why are you using this Microsoft shit?! Huh? BE FREE USE GNU/LINUX (or at least BSD)!!! -- Gustavo Sverzut Barbieri & Ivens Prates Telles Alves   ",0
	STR_PROC_2	DB	"......................................... LINUX            .-'`-.              .. RULEZ           ( O__O )    /\       ..                  ) \/  (   / |       .. Say Hello to Tux/       \_/  /       ..                / |.-.-.     /        ..               /  \  ^  )   /         .. ASCII ART by  |   \ +  \   \         ..    GSB     .-.-.-./     )   \ .-._   ..            \ ^ ^ /'-._.-'    /  '_\  ..oOo.oOo.oOo.o\___/._________.-|_____)o.................................................................................. LINUX            .-'`-.              .. RULEZ!!!        ( o__o )             ..                  ) \/  (     _.-     .. You: Hello Tux! /       \_.-'  /     ..                / |.-.-.       /      ..               /  \  ^  )   .-'       .. ASCII ART by  |   \ +  \   \         ..    GSB     .-.-.-./     )  .-.-.-.   ..            \ ^ ^ /'-._.-'  \ ^ ^ /   ..oOo.oOo.oOo.o\___/._________.\___/.oOo.................................................................................. LINUX            .-'`-.              .. RULEZ           ( O__O )             ..                  ) \/  (             .. Tux: Hello!     /       \___.---.    ..                / |.-.-.        _/    ..               /  \  ^  )   .--'      .. ASCII ART by  |   \ +  \   \         ..    GSB     .-.-.-./     )   \ .-._   ..            \ ^ ^ /'-._.-'    /  '_\  ..oOo.oOo.oOo.o\___/._________.-|_____)o.................................................................................. LINUX            .-'`-.              .. RULEZ!!!        ( o__o )             ..                  ) \/  (     _.-     .. BOTH: NO PATENTS/       \_.-'  /     ..                / |.-.-.       /      ..               /  \  ^  )   .-'       .. ASCII ART by  |   \ +  \   \         ..    GSB     .-.-.-./     )   \ .-._   ..            \ ^ ^ /'-._.-'    /  '_\  ..oOo.oOo.oOo.o\___/._________.-|_____)o.........................................",0
	STR_PROC_5_RUN  DB	"RUNNING",0
	STR_PROC_5_PAU  DB	"PAUSED ",0
	Author1		DB	"Gustavo Sverzut Barbieri <ra008849@ic.unicamp.br>",0
	Author2		DB	"Ivens Prates Telles Alves <ra008908@ic.unicamp.br>",0







[SEGMENT .bss]         ;Uninitialised data segment
	Stack_Area_P1	resb	512
	Stack_Area_P2	resb	512
	Stack_Area_P3	resb	512
	Stack_Area_P4	resb	512
	Stack_Area_P5	resb	512



