diff --git a/kernel/context_switch.s b/kernel/context_switch.s new file mode 100644 index 0000000..0e68648 --- /dev/null +++ b/kernel/context_switch.s @@ -0,0 +1,25 @@ +.global ctx_switch + +; void ctx_switch(uint32_t **old_sp_ptr, uint32_t *new_sp); +; Arguments on stack (cdecl convention): +; [ESP + 4] -> old_sp_ptr (pointer to the 'stack_ptr' field of current task) +; [ESP + 8] -> new_sp (value of 'stack_ptr' of the next task) + +ctx_switch: + ; 1. Save the context of the CURRENT task + pushf ; Save EFLAGS (CPU status flags) + pusha ; Save all General Purpose Regs (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI) + + ; 2. Save the current stack pointer (ESP) into the pointer passed as 1st arg + mov eax, [esp + 40] ; Get 1st argument (old_sp_ptr). Offset 40 = 36 (regs) + 4 (ret addr) + mov [eax], esp ; *old_sp_ptr = ESP + + ; 3. Load the stack pointer of the NEW task + mov esp, [esp + 44] ; Get 2nd argument (new_sp). Offset 44 = 40 + 4 + + ; 4. Restore the context of the NEW task + popa ; Restore all General Purpose Regs + popf ; Restore EFLAGS + + ; 5. Jump to the new task (The 'ret' pops EIP from the new stack) + ret