Computer Architecture and Assembly Languagecaspl162/wiki.files/PS07_162[1].pdf · main() scheduler...

26
Practical Session 7 Computer Architecture and Assembly Language

Transcript of Computer Architecture and Assembly Languagecaspl162/wiki.files/PS07_162[1].pdf · main() scheduler...

Practical Session 7

Computer Architecture and

Assembly Language

Co-Routines

• co-routines are assembly

implementation of threads

• each co-routine decides to which co-routine

to pass a control (unlike “usual” threads)

We would implement “silly” round robin scheduling algorithm:

main() scheduler co-routine1 scheduler co-routine2 scheduler

co-routine1 scheduler co-routine2 scheduler main()

Co-routine state• co-routine is denoted by Coi (i is co-routine’s id)

• scheduler is also a co-routine

• co-routine suspends itself after some “time slice”

• co-routine resumes a scheduler

• co-routine should save its current state before it

suspends itself (in order to continue its execution later)

• stack state

• registers

• flags

• stack pointer (ESP)

• instructions pointer (EIP)

Co-routine structure

STKSIZE equ 16*1024 ;(16 Kb)

STKi: resb STKSIZE

COi: dd Functioni ; pointer to co-routine function

Flags: dd 0 ; 0 if co-routine is not initialized, 1 otherwise

SPi: dd STKi + STKSIZE ; pointer to the beginning of co-routine stack

Co-routine structure:

We define an array of co-routines’ structures:

why SPi points to the end of stack ?

to be able to use push and pop stack functionality with ESP

SPi0Funci

co-routine structure co-routine stack

STKSZ equ 16*1024 ; co-routine stack sizeCODEP equ 0 ; offset of pointer to co-routine function in co-routine structure FLAGSP equ 4 ; offset of pointer to flags co-routine structure SPP equ 8 ; offset of pointer to co-routine stack in co-routine structure section .rodata

align 16global numco

numco: dd 3CORS: dd CO1

dd CO2dd CO3

section .dataalign 16

CO1: dd Function1 ; structure for first co-routineFlags1: dd 0SP1: dd STK1+STKSZCO2: dd Function1 ; structure for second co-routineFlags2: dd 0SP2: dd STK2+STKSZCO3: dd Function2 ; structure for third co-routineFlags3: dd 0SP3: dd STK3+STKSZsection .bss

align 16CURR: resd 1SPT: resd 1 ; temporary stack pointer variableSPMAIN: resd 1 ; stack pointer of mainSTK1: resb STKSZSTK2: resb STKSZSTK3: resb STKSZ

Variables Declaration

SPi0Funci

Co-routine initialization - save initial co-routine state

co_init:

mov eax, [ebx+CODEP] ; get initial PC

mov esp, [EBX+SPP] ; get initial SP

push eax ; push initial “return” address

pushfd ; push flags

pushad ; push all other registers

mov [ebx+SPP], esp ; save new SPi value (after all the pushes)

co-routine structure co-routine stack

init_co_from_c:

mov ebx, [ebp+8] ; get co-routine ID number

mov ebx, [4*ebx + CORS] ; get COi pointer

call co_init

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

SPi0Funci

Co-routine initialization - save initial co-routine state

co_init:

mov eax, [ebx+CODEP] ; get initial PC

mov esp, [EBX+SPP] ; get initial SP

push eax ; push initial “return” address

pushfd ; push flags

pushad ; push all other registers

mov [ebx+SPP], esp ; save new SPi value (after all the pushes)

co-routine structure co-routine stack

init_co_from_c:

mov ebx, [ebp+8] ; get co-routine ID number

mov ebx, [4*ebx + CORS] ; get COi pointer

call co_init

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

ESP

FunciSPi0Funci

Co-routine initialization - save initial co-routine state

co_init:

mov eax, [ebx+CODEP] ; get initial PC

mov esp, [EBX+SPP] ; get initial SP

push eax ; push initial “return” address

pushfd ; push flags

pushad ; push all other registers

mov [ebx+SPP], esp ; save new SPi value (after all the pushes)

co-routine structure co-routine stack

init_co_from_c:

mov ebx, [ebp+8] ; get co-routine ID number

mov ebx, [4*ebx + CORS] ; get COi pointer

call co_init

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

ESP

FunciEFlagsSPi0Funci

Co-routine initialization - save initial co-routine state

co_init:

mov eax, [ebx+CODEP] ; get initial PC

mov esp, [EBX+SPP] ; get initial SP

push eax ; push initial “return” address

pushfd ; push flags

pushad ; push all other registers

mov [ebx+SPP], esp ; save new SPi value (after all the pushes)

co-routine structure co-routine stack

init_co_from_c:

mov ebx, [ebp+8] ; get co-routine ID number

mov ebx, [4*ebx + CORS] ; get COi pointer

call co_init

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

ESP

FunciEFlagsregistersSPi0Funci

Co-routine initialization - save initial co-routine state

co_init:

mov eax, [ebx+CODEP] ; get initial PC

mov esp, [EBX+SPP] ; get initial SP

push eax ; push initial “return” address

pushfd ; push flags

pushad ; push all other registers

mov [ebx+SPP], esp ; save new SPi value (after all the pushes)

co-routine structure co-routine stack

init_co_from_c:

mov ebx, [ebp+8] ; get co-routine ID number

mov ebx, [4*ebx + CORS] ; get COi pointer

call co_init

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

ESP

FunciEFlagsregistersSPi1Funci

Co-routine initialization - save initial co-routine state

co_init:

mov eax, [ebx+CODEP] ; get initial PC

mov esp, [EBX+SPP] ; get initial SP

push eax ; push initial “return” address

pushfd ; push flags

pushad ; push all other registers

mov [ebx+SPP], esp ; save new SPi value (after all the pushes)

co-routine structure co-routine stack

init_co_from_c:

mov ebx, [ebp+8] ; get co-routine ID number

mov ebx, [4*ebx + CORS] ; get COi pointer

call co_init

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

ESP

Co-routine initializationsection .text

align 16extern printfglobal init_co_from_cglobal start_co_from_cglobal end_co

init_co_from_c:push EBPmov EBP, ESPpush EBXmov EBX, [EBP+8] ; EBX contains a number of the co-routine to be initializedmov EBX, [EBX*4+CORS] ; EBX contains a pointer to co-routine structure to be initializedcall co_initpop EBXpop EBPret

co_init:pushadbts dword [EBX+FLAGSP],0 ; test if already initializedjc init_donemov EAX,[EBX+CODEP] ; get initial PCmov [SPT], ESP ; save original SPmov ESP,[EBX+SPP] ; get initial SPmov EBP, ESP ; also use as EBPpush EAX ; push initial "return" address (initial PC)pushfd ; push flagspushad ; push all other registersmov [EBX+SPP],ESP ; save new SP in structuremov ESP, [SPT] ; restore original SP

init_done:popadret ‘bts’ instruction tests one bit of its first operand, whose index is

given by the second operand, and stores the value of that bit in

the carry flag (CF). In addition, ‘bts’ sets the bit to be 1.

Start co-routine schedulerWe start scheduling by suspending main() and resuming a scheduler co-routine.

start_co_from_c:push EBP

mov EBP, ESP

pushad

mov [SPMAIN], ESP ; save ESP of main ()

mov EBX, [EBP+8] ; gets ID number of a scheduler

mov EBX, [EBX*4 + CORS] ; gets a pointer to a scheduler structure

jmp do_resume ; resume a scheduler co-routine

We end scheduling by going back to main().

end_co:mov ESP, [SPMAIN] ; restore state of main code

popad

pop EBP

ret

main() {

/* initialize co-routines*/

for(i = 0; i < numco; i++)

init_co_from_c(i);

/* start a scheduler co-routine*/

start_co_from_c (2);

}

Scheduler co-routine functionScheduler function is started by main.

scheduler_Function:

pick up some thread ID i

mov EBX, [CORS + i*4] ; resumes Coi

call resume

pick up some other thread ID j

mov EBX, [CORS + j*4] ; resumes Coj

call resume…

jmp end_co ; resume main

‘call resume’•save a state of the current co-routine•resume a state of the next co-routine (EBX should contain a pointer to it)

EBX is pointer to co-init structure of the co-routine to be resumed.CURR holds a pointer to co-init structure of the current co-routine.

resume: ; save state of callerpushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP ; save current SP

do_resume: ; load SP for resumed co-routinemov ESP, [EBX+SPP]mov [CURR], EBXpopad ; restore resumed co-routine statepopfdret ; "return" to resumed co-routine!

•after ‘call resume’ return address (i.e. EIP) is pushed automatically into (co-routine) stack•we only have to save EFLAGS, ESP, and registers

Function2This function used as code for co-routine 3 (scheduler)

FMT2: db "Function2, co %lx, called by %lx, pass %ld", 10, 0

Function2:push dword 1push dword [CORS] ; indeed, called by mainpush dword [CURR]push dword FMT2call printfadd ESP, 16mov EBX, [CORS] ; resume CO1call resume

push dword 2push dword [CORS]push dword [CURR]push dword FMT2call printfadd ESP, 16

mov EBX, [CORS+4] ; resume CO2call resumepush dword 3push dword [CORS+4]push dword [CURR]push dword FMT2call printfadd ESP, 16mov EBX, [CORS] ; resume CO1call resumepush dword 4push dword [CORS]push dword [CURR]push dword FMT2call printfadd ESP, 16mov EBX, [CORS+4] ; resume CO2call resumejmp end_co ; resume main

Function1

This function used as code for co-routines 1 and 2

FMT1: db "Function1, co %lx, called by %lx, pass %ld", 10, 0

Function1:push dword 1push dword [CORS+8]push dword [CURR]push dword FMT1call printfadd ESP, 16mov EBX, [CORS+8] ; resume a schedulercall resume

push dword 2push dword [CORS+8]push dword [CURR]push dword FMT1call printfadd ESP, 16mov EBX, [CORS+8] ; resume a schedulercall resume

Run example – data declaration

CURR

SPT

SPMAIN

STK1

STK2

STK3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

0 Flags1

SP1

Function1 CO2

0 Flags2

SP2

Function2 CO3

0 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

After co-routine initialization

CURR

SPT

SPMAIN

STK1

Registers

Flags

Function1

STK2

Registers

Flags

Function1

STK3

Registers

Flags

Function2

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

Resuming - right before

CO2 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

STK2

……….

……….

STK3

Registers

Flags

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

.bss .data

ESP

Resuming – resume is called

CO2 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

STK2

Addr2

……….

……….

STK3

Registers

Flags

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP

Resuming – backup registers

CO2 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

Registers STK2

Flags

Addr2

……….

……….

STK3

Registers

Flags

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP

Resuming – backup stack pointer

CO2 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

Registers STK2

Flags

Addr2

……….

……….

STK3

Registers

Flags

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP

Resuming - load stack pointer of resume co-routine

CO2 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

Registers STK2

Flags

Addr2

……….

……….

STK3

Registers

Flags

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP

Resuming – set current co-routine variable

CO3 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

Registers STK2

Flags

Addr2

……….

……….

STK3

Registers

Flags

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP

Resuming – restore a state of loaded co-routine

CO3 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

Registers STK2

Flags

Addr2

……….

……….

STK3

Addr3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP

Resuming – go to execute the loaded co-routine

CO3 CURR

SPT

SPMAIN

STK1

Registers

Flags

Addr1

Registers STK2

Flags

Addr2

……….

……….

STK3

3 numco

CO1 CORS

CO2

CO3

Function1 CO1

1 Flags1

SP1

Function1 CO2

1 Flags2

SP2

Function2 CO3

1 Flags3

SP3

0 COUNTER

3 MAX_ITER

.bss .data

resume:pushfdpushadmov EDX, [CURR]mov [EDX+SPP],ESP

do_resume:mov ESP, [EBX+SPP] mov [CURR], EBXpopadpopfdret

ESP