|
Table of Content | Chapter Nineteen
(Part 9) |
| CHAPTER NINETEEN: PROCESSES COROUTINES AND CONCURRENCY (Part 8) |
| 19.3.2 - 32-bit Coroutines |
The existing Standard Library (v1.0) coroutine package is
not suitable for programs that use the 80386 and later 32 bit register sets. As mentioned
earlier
the problem lies in the fact that the Standard Library only preserves the 16-bit
registers when switching between processes. However
it is a relatively trivial extension
to modify the Standard Library so that it saves 32 bit registers. To do so
just change
the definition of the pcb (to make room for the 32 bit registers) and the sl_cocall
routine:
.386 option segment:use16 dseg segment para public 'data' wp equ <word ptr> ; 32-bit PCB. Note we only keep the L.O. 16 bits of SP since we are ; operating in real mode. pcb32 struc regsp word ? regss word ? regip word ? regcs word ? regeax dword ? regebx dword ? regecx dword ? regedx dword ? regesi dword ? regedi dword ? regebp dword ? regds word ? reges word ? regflags dword ? pcb32 ends DefaultPCB pcb32 <> DefaultCortn pcb32 <> CurCoroutine dd DefaultCortn ;Points at the currently executing ; coroutine. dseg ends cseg segment para public 'slcode' ;============================================================================ ; ; Coroutine support. ; ; COINIT- ES:DI contains the address of the current (default) process. CoInit32 proc far assume ds:dseg push ax push ds mov ax dseg mov ds ax mov wp dseg:CurCoroutine di mov wp dseg:CurCoroutine+2 es pop ds pop ax ret CoInit32 endp ; COCALL32- transfers control to a coroutine. ES:DI contains the address ; of the PCB. This routine transfers control to that coroutine and then ; returns a pointer to the caller's PCB in ES:DI. cocall32 proc far assume ds:dseg pushfd push ds push es ;Save these for later push edi push eax mov ax dseg mov ds ax cli ;Critical region ahead. ; Save the current process' state: les di dseg:CurCoroutine pop es:[di].pcb32.regeax mov es:[di].pcb32.regebx ebx mov es:[di].pcb32.regecx ecx mov es:[di].pcb32.regedx edx mov es:[di].pcb32.regesi esi pop es:[di].pcb32.regedi mov es:[di].pcb32.regebp ebp pop es:[di].pcb32.reges pop es:[di].pcb32.regds pop es:[di].pcb32.regflags pop es:[di].pcb32.regip pop es:[di].pcb32.regcs mov es:[di].pcb32.regsp sp mov es:[di].pcb32.regss ss mov bx es ;Save so we can return in mov ecx edi ; ES:DI later. mov edx es:[di].pcb32.regedi mov es es:[di].pcb32.reges mov di dx ;Point es:di at new PCB mov wp dseg:CurCoroutine di mov wp dseg:CurCoroutine+2 es mov es:[di].pcb32.regedi ecx ;The ES:DI return values. mov es:[di].pcb32.reges bx ; Okay switch to the new process: mov ss es:[di].pcb32.regss mov sp es:[di].pcb32.regsp mov eax es:[di].pcb32.regeax mov ebx es:[di].pcb32.regebx mov ecx es:[di].pcb32.regecx mov edx es:[di].pcb32.regedx mov esi es:[di].pcb32.regesi mov ebp es:[di].pcb32.regebp mov ds es:[di].pcb32.regds push es:[di].pcb32.regflags push es:[di].pcb32.regcs push es:[di].pcb32.regip push es:[di].pcb32.regedi mov es es:[di].pcb32.reges pop edi iret cocall32 endp ; CoCall32l works just like cocall above except the address of the pcb ; follows the call in the code stream rather than being passed in ES:DI. ; Note: this code does *not* return the caller's PCB address in ES:DI. ; cocall32l proc far assume ds:dseg push ebp mov bp sp pushfd push ds push es push edi push eax mov ax dseg mov ds ax cli ;Critical region ahead. ; Save the current process' state: les di dseg:CurCoroutine pop es:[di].pcb32.regeax mov es:[di].pcb32.regebx ebx mov es:[di].pcb32.regecx ecx mov es:[di].pcb32.regedx edx mov es:[di].pcb32.regesi esi pop es:[di].pcb32.regedi pop es:[di].pcb32.reges pop es:[di].pcb32.regds pop es:[di].pcb32.regflags pop es:[di].pcb32.regebp pop es:[di].pcb32.regip pop es:[di].pcb32.regcs mov es:[di].pcb32.regsp sp mov es:[di].pcb32.regss ss mov dx es:[di].pcb32.regip ;Get return address (ptr to mov cx es:[di].pcb32.regcs ; PCB address. add es:[di].pcb32.regip 4 ;Skip ptr on return. mov es cx ;Get the ptr to the new pcb mov di dx ; address then fetch the les di es:[di] ; pcb val. mov wp dseg:CurCoroutine di mov wp dseg:CurCoroutine+2 es ; Okay switch to the new process: mov ss es:[di].pcb32.regss mov sp es:[di].pcb32.regsp mov eax es:[di].pcb32.regeax mov ebx es:[di].pcb32.regebx mov ecx es:[di].pcb32.regecx mov edx es:[di].pcb32.regedx mov esi es:[di].pcb32.regesi mov ebp es:[di].pcb32.regebp mov ds es:[di].pcb32.regds push es:[di].pcb32.regflags push es:[di].pcb32.regcs push es:[di].pcb32.regip push es:[di].pcb32.regedi mov es es:[di].pcb32.reges pop edi iret cocall32l endp cseg ends end
|
Table of Content | Chapter Nineteen (Part 9) |
Chapter Nineteen: Processes
Coroutines and Concurrency (Part 8)
29 SEP 1996