139 lines
4.4 KiB
NASM
139 lines
4.4 KiB
NASM
;*****************************************************************************
|
|
;* *
|
|
;* C O R O U T I N E *
|
|
;* *
|
|
;*---------------------------------------------------------------------------*
|
|
;* Beschreibung: Assemblerdarstellung der 'struct CoroutineState' aus *
|
|
;* CoroutineState.h *
|
|
;* *
|
|
;* Die Reihenfolge der Registerbezeichnungen muss unbedingt *
|
|
;* mit der von 'struct CoroutineState' uebereinstimmen. *
|
|
;* *
|
|
;* Autor: Olaf Spinczyk, TU Dortmund *
|
|
;*****************************************************************************
|
|
|
|
%include "kernel/threads/Thread.inc"
|
|
|
|
; EXPORTIERTE FUNKTIONEN
|
|
|
|
[GLOBAL Thread_switch]
|
|
[GLOBAL Thread_start]
|
|
|
|
; IMPLEMENTIERUNG DER FUNKTIONEN
|
|
|
|
[SECTION .text]
|
|
|
|
; COROUTINE_START : Startet die erste Coroutine ueberhaupt.
|
|
;
|
|
; C Prototyp: void Coroutine_start (struct CoroutineState* regs);
|
|
|
|
;; Coroutine_start is called with one arg: CoroutineState* regs, so the main stack looks like this:
|
|
;; NOTE: Since this assembly is not generated by the compiler, there is no ebp prelude.
|
|
;; To address parameters we use esp.
|
|
;; == High address ==
|
|
;; *REGS
|
|
;; ESP: RET ADDR
|
|
;; == Low address ==
|
|
Thread_start:
|
|
; *
|
|
; * Hier muss Code eingefuegt werden
|
|
; *
|
|
|
|
;; Set eax to the address where the CoroutineState struct is in memory:
|
|
mov eax, [esp + 0x4]
|
|
|
|
;; Now eax points to the beginning of CoroutineState:
|
|
;; struct CoroutineState {
|
|
;; == Low address ==
|
|
;; EAX: void *ebx;
|
|
;; void *esi;
|
|
;; void *edi;
|
|
;; void *ebp;
|
|
;; void *esp;
|
|
;; == High address ==
|
|
;; };
|
|
|
|
;; Load the contents of CoroutineState to the registers
|
|
mov esp, [eax + esp_offset]
|
|
|
|
;; The stackpointer now points to the coroutine stack
|
|
;; struct CoroutineState {
|
|
;; == High address ==
|
|
;; *OBJECT
|
|
;; 0x13115
|
|
;; SP: *KICKOFF
|
|
;; == Low address ==
|
|
;; };
|
|
|
|
;; Return to kickoff
|
|
ret
|
|
|
|
|
|
; COROUTINE_SWITCH : Coroutinenumschaltung. Der aktuelle Registersatz wird
|
|
; gesichert und der Registersatz der neuen Coroutine
|
|
; wird in den Prozessor eingelesen.
|
|
;
|
|
; C Prototyp: void Coroutine_switch (struct CoroutineState* regs_now, struct CoroutineState* reg_then);
|
|
;
|
|
; Achtung: Die Parameter werden von rechts nach links uebergeben.
|
|
;
|
|
;; == High address ==
|
|
;; *REGS_THEN
|
|
;; *REGS_NOW
|
|
;; SP --> RET ADDR
|
|
;; == Low address ==
|
|
Thread_switch:
|
|
; *
|
|
; * Hier muss Code eingefuegt werden
|
|
; *
|
|
;; Save current coroutine registers
|
|
;; == High address ==
|
|
;; *REGS_THEN
|
|
;; *REGS_NOW
|
|
;; RET ADDR
|
|
;; SP --> EAX
|
|
;; == Low address ==
|
|
push eax ; backup eax before using it as index
|
|
mov eax, [esp + 0x8]
|
|
|
|
add esp, 0x4 ; store the original esp
|
|
mov [eax + esp_offset], esp
|
|
sub esp, 0x4
|
|
|
|
mov [eax + ebx_offset], ebx ; store other regs
|
|
mov [eax + esi_offset], esi
|
|
mov [eax + edi_offset], edi
|
|
mov [eax + ebp_offset], ebp
|
|
mov [eax + ecx_offset], ecx
|
|
mov [eax + edx_offset], edx
|
|
|
|
pushf ; store eflags
|
|
pop ebx
|
|
mov [eax + efl_offset], ebx
|
|
|
|
pop ebx ; store eax
|
|
mov [eax + eax_offset], ebx
|
|
|
|
;; Load next coroutine registers ============================================================
|
|
mov eax, [esp + 0x8]
|
|
|
|
mov ebx, [eax + efl_offset] ; restore eflags
|
|
push ebx ; could be pushed directly from address but i didn't want to specify wordsize
|
|
popf
|
|
|
|
mov ebx, [eax + ebx_offset] ; restore other regs
|
|
mov esi, [eax + esi_offset]
|
|
mov edi, [eax + edi_offset]
|
|
mov ebp, [eax + ebp_offset]
|
|
mov esp, [eax + esp_offset]
|
|
mov ecx, [eax + ecx_offset]
|
|
mov edx, [eax + edx_offset]
|
|
mov eax, [eax + eax_offset] ; restore eax
|
|
|
|
;; Enable interrupts again
|
|
sti
|
|
|
|
;; NOTE: The stackpointer points to kickoff if the next coroutine was just initialized.
|
|
;; Otherwise it just points somewhere in the next coroutines stack
|
|
ret
|