2021-04-03 - i386 coroutines
I have been trying to add coroutines to a hobby OS. Lots of the examples are in Intel syntax, 64-bit architecture, or sell themselves as windows/linux/mac only.
Finally got a working solution after tweaking a few examples. The AT&T syntax assembly and the coroutine init code came from here: https://stackoverflow.com/questions/62766352/assembly-coroutines
A stacksize of 8192 seems to work (based on the comments of the stackoverflow question) and stack can be malloc-ed or not. "ptr[5]" can point to our switch task or a cleanup subroutine that also runs switch task at the end.
uint32_t* ptr; /* the new stack pointer */
ptr = (uint32_t*)((uint8_t*)stack + stacksize);
ptr -= 7;
ptr[0] = 1; /* edi */
ptr[1] = 2; /* esi */
ptr[2] = 3; /* ebx */
ptr[3] = (uint32_t)(ptr + 5); /* ebp */
ptr[4] = (uint32_t)func;
ptr[5] = (uint32_t)switch_task; /* return instruction address */
.global switch_task
switch_task:
mov 4(%esp), %ecx
mov 8(%esp), %edx
# Save registers
push %ebp
push %ebx
push %esi
push %edi
# Save old stack
mov %esp, (%ecx)
# Load new stack
mov (%edx), %esp
# Restore registers
pop %edi
pop %esi
pop %ebx
pop %ebp
ret
← Back to /snippets