From 4f94ccdc9912f0b21792dabca652dba4b2550f02 Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Mon, 23 May 2022 09:11:59 +0200 Subject: [PATCH] implement asm coroutine --- c_os/kernel/corouts/Coroutine.asm | 68 +++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/c_os/kernel/corouts/Coroutine.asm b/c_os/kernel/corouts/Coroutine.asm index 07ceb56..2e38a75 100755 --- a/c_os/kernel/corouts/Coroutine.asm +++ b/c_os/kernel/corouts/Coroutine.asm @@ -27,25 +27,85 @@ ; ; C Prototyp: void Coroutine_start (struct CoroutineState* regs); +;; Coroutine_start is called with one arg: CoroutineState* regs, so the main stack looks like this: +;; == High address == +;; *REGS +;; SP: RET ADDR +;; == Low address == Coroutine_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); +; 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 == Coroutine_switch: - ; * ; * Hier muss Code eingefuegt werden ; * + ;; Make eax point to beginning of regs_now in memory + mov eax, [esp + 0x4] + + ;; Save current coroutine registers + mov [eax + ebx_offset], ebx + mov [eax + esi_offset], esi + mov [eax + edi_offset], edi + mov [eax + ebp_offset], ebp + mov [eax + esp_offset], esp + + ;; Make eax point to beginning of regs_then in memory + mov eax, [esp + 0x8] + + ;; Load next coroutine registers + mov ebx, [eax + ebx_offset] + mov esi, [eax + esi_offset] + mov edi, [eax + edi_offset] + mov ebp, [eax + ebp_offset] + mov esp, [eax + esp_offset] + + ;; Stackpointer now points to kickoff address, ret jumps there + ;; NOTE: The stackpointer only points to kickoff if the next coroutine was just initialized. + ;; Otherwise it just points somewhere in the next coroutines stack + ret