I'm trying to write a scheduler to run what we call "fibers". Unfortunately, I'm not really used to writing inline assembly.
typedef struct {
//fiber's stack
long rsp;
long rbp;
//next fiber in ready list
struct fiber *next;
} fiber;
//currently executing fiber
fiber *fib;
So the very first task is - obviously - creating a fiber for the main function so it can be suspended.
int main(int argc, char* argv[]){
//create fiber for main function
fib = malloc(sizeof(*fib));
__asm__(
"movq %%rsp, %0;"
"movq %%rbp, %1;"
: "=r"(fib->rsp),"=r"(fib->rbp)
);
//jump to actual main and execute
__asm__(...);
}
This gets compiled to
movl $24, %edi #,
call malloc #
#APP
# 27 "scheduler.c" 1
movq %rsp, %rcx;movq %rbp, %rdx; # tmp92, tmp93
# 0 "" 2
#NO_APP
movq %rax, fib(%rip) # tmp91, fib
movq %rcx, (%rax) # tmp92, MEM[(struct fiber *)_3].rsp
movq %rdx, 8(%rax) # tmp93, MEM[(struct fiber *)_3].rbp
Why does this compile movs into temporary registers? Can I somehow get rid of them?
The first version of this question had asm output from gcc -O0, with even more instructions and temporaries.
Turning on optimisations does not get rid of them.
rbpspecial for your fibers? Surely you need to save/restore all registers.rspis the only one that's special: you can use it to find a fiber's stack (where you saved the other registers, I assume). - Peter Cordesrsp, pop all the other regs one at a time, includingrbp. Boom, you're back. If the function you resumed was usingrbpas a frame pointer, then it still is. You've resumed from the saved context, restoring all state except for the memory where you stored registers. (Remember that the SystemV AMD64 ABI uses a 128B red-zone, so before pushing registers, you shouldadd $-128, %rspso you save them below the current function's red-zone. After popping the state back into regs,sub $-128, %rsp. (-128 fits in animm8, but +128 doesn't, hence the double-negative) - Peter Cordes