rendered paste body STKSZ equ 16*1024
CODEP equ 0
FLAGSP equ 4
SPP equ 8
BUFFCNT equ 10
section .rodata
align 16
global numco
numco: dd 4
CORS: dd CO1
dd CO2
dd CO3
dd CO4
section .data
align 16
; Structure for first co-routine (writer)
CO1: dd Function1
Flags1: dd 0
SP1: dd STK1+STKSZ
; Structure for second co-routine (reader1)
CO2: dd Function2
Flags2: dd 0
SP2: dd STK2+STKSZ
; Structure for third co-routine (reader2)
CO3: dd Function3
Flags3: dd 0
SP3: dd STK3+STKSZ
; Structure for forth co-routine (scheduler)
CO4: dd Function4
Flags4: dd 0
SP4: dd STK4+STKSZ
SWITCH: dd 0 ; indicator - reader1/reader2
EXIT: db 0 ; indicator - becomes 1 if we should exit
FINISH: db 0 ; indicator - becomes 1 if input is fully written
MUX: db 1 ; indicator - which reader to choose
section .bss
align 16
CURR: resd 1
SPT: resd 1
SPMAIN: resd 1
STK1: resb STKSZ
STK2: resb STKSZ
STK3: resb STKSZ
STK4: resb STKSZ
BUFFER: resb 4
INPUT: resb 4
BUFF: resb 4
section .text
align 16
extern printf
extern gets
global init_co_from_c
global start_co_from_c
global end_co
; Initalize a co-routine number given as an argument from C
init_co_from_c:
push EBP
mov EBP, ESP
push EBX
mov EBX, [EBP+8]
mov EBX, [EBX*4+CORS]
call co_init
pop EBX
pop EBP
ret
; EBX is pointer to co-routine structure to initialize
co_init:
pusha
bts dword [EBX+FLAGSP],0 ; test if already initialized
jc init_done
mov EAX,[EBX+CODEP] ; Get initial PC
mov [SPT], ESP
mov ESP,[EBX+SPP] ; Get initial SP
mov EBP, ESP ; Also use as EBP
push EAX ; Push initial "return" address
pushf ; and flags
pusha ; and all other regs
mov [EBX+SPP],ESP ; Save new SP in structure
mov ESP, [SPT] ; Restore original SP
init_done:
popa
ret
; EBX is pointer to co-init structure of co-routine to be resumed
; CURR holds a pointer to co-init structure of the curent co-routine
resume:
pushf ; Save state of caller
pusha
mov EDX, [CURR]
mov [EDX+SPP],ESP ; Save current SP
do_resume:
mov ESP, [EBX+SPP] ; Load SP for resumed co-routine
mov [CURR], EBX
popa ; Restore resumed co-routine state
popf
ret ; "return" to resumed co-routine!
; C-callable start of the first co-routine
start_co_from_c:
push EBP
mov EBP, ESP
pusha
mov [SPMAIN], ESP ; Save SP of main code
mov EBX, [EBP+8] ; Get number of co-routine
mov EBX, [EBX*4+CORS] ; and pointer to co-routine structure
jmp do_resume
; End co-routine mechanism, back to C main
end_co:
mov ESP, [SPMAIN] ; Restore state of main code
popa
pop EBP
ret
; Example functions using co-routine mechanism
WRITERES: db "Writer Resumes.", 10, 0
READ1RES: db "Reader1 Resumes.", 10, 0
READ2RES: db "Reader2 Resumes.", 10, 0
SCHEDRES: db "Scheduler Resumes.", 10, 0
WRITER: db "Writer: %s", 10, 0
READ1: db "Reader1: %s", 10, 0
READ2: db "Reader2: %s", 10, 0
SCHED: db "Scheduler: %s", 10, 0
WRITEPROM: db "Writer: Hello, master. What can I write and read for you today? ", 0
WRITING: db "Writer: Writing %s.", 10, 0
WRITEFIN: db "Writer: I have finished writing your words of wisdom, sir.", 10, 0
READSORR: db "Terribly sorry, sir. The buffer is locked by the writer.", 0
READFIN1: db "Reader1: Ah, a fine read, sir. You wrote: %s.", 10, 0
READFIN2: db "Reader2: Ah, a fine read, sir. You wrote: %s.", 10, 0
GOODBYE: db "Goodbye, master.", 0
; This function used as code for co-routines 0 and 1
Function1:
push dword WRITERES ; display resume
call printf
add esp, 4
NeWInput:
push dword WRITEPROM
call printf
add esp, 4
mov ecx, INPUT
pusha
push ecx
call gets
add esp, 4
popa
pusha
push ecx
call printf
add esp, 4
popa
mov byte[FINISH], 0
cmp byte[ecx], 113 ; q
je quit
mov edx, BUFF
loop_init:
mov esi, 0 ; loop counter till 10
mov ebx, BUFFER
func1_loop:
mov al, byte[ecx]
cmp al, 0
je end_string
mov byte[ebx], al
;mov byte[edx], al
inc ebx
inc ecx
;inc edx
inc esi
cmp esi ,BUFFCNT
jne func1_loop
end_10_chars:
mov byte[ebx], 0
pusha
push dword BUFFER
push dword WRITING
call printf
add esp, 8
popa
mov ebx, [CORS + 12]
call dword resume
pusha
push dword WRITERES ; display resume
call printf
add esp, 4
popa
jmp loop_init
end_string:
mov byte[FINISH], 1
mov byte[ebx], 0
;mov byte[edx], 0
pusha
push dword BUFFER
push dword WRITING
call printf
add esp, 8
popa
pusha
push dword WRITEFIN
call printf
add esp, 4
popa
mov ebx, [CORS + 12]
call dword resume
jmp Function1
quit:
mov byte[EXIT], 1
pusha
push dword GOODBYE
push dword WRITER
call printf
add esp, 8
popa
mov ebx, [CORS + 12]
call dword resume
; This function used as code for co-routine 2
Function2:
first_reader:
mov eax, READ1RES
pusha
push eax
call printf
add esp, 4
popa
cmp byte[EXIT], 1
je goodbye1
cmp byte[FINISH], 1
jne sorry1
read_buffer1:
pusha
push dword INPUT
push dword READFIN1
call printf
add esp, 8
popa
jmp func2_loop1
sorry1:
push dword READSORR
push dword READ1
call printf
add esp, 8
jmp func2_loop1
goodbye1:
push dword GOODBYE
push dword READ1
call printf
add esp, 8
func2_loop1:
mov ebx, [CORS + 12]
call dword resume
jmp first_reader
; This function used as code for co-routine 3
Function3:
second_reader:
mov eax, READ2RES
push eax
call printf
add esp, 4
cmp byte[EXIT], 1
je goodbye2
cmp byte[FINISH], 1
jne sorry2
read_buffer2:
push dword INPUT
push dword READFIN2
call printf
add esp, 8
jmp func2_loop2
sorry2:
push dword READSORR
push dword READ2
call printf
add esp, 8
jmp func2_loop2
goodbye2:
push dword GOODBYE
push dword READ2
call printf
add esp, 8
func2_loop2:
mov ebx, [CORS + 12]
call dword resume
jmp second_reader
; This function used as code for co-routine 3
Function4:
Writer:
push dword SCHEDRES
call printf
add esp, 4
mov ebx, [CORS]
call dword resume
push dword INPUT;
call printf
add esp, 4
cmp byte[EXIT], 1
je Reader1
cmp byte[MUX], 2
je Reader2
Reader1:
push dword SCHEDRES
call printf
add esp, 4
mov ebx, [CORS + 4]
call dword resume
mov byte[MUX], 2
cmp byte[EXIT], 1
jne Writer
Reader2:
push dword SCHEDRES
call printf
add esp, 4
mov ebx, [CORS + 8]
call dword resume
mov byte[MUX], 1
cmp byte[EXIT], 1
jne Writer
finish:
push dword SCHEDRES
call printf
add esp, 4
cmp byte[EXIT], 1
jne Function3
push dword GOODBYE
push dword SCHED
call printf
add esp, 8
jmp end_co