sheenobu dot net

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