Explanation of Asm code
Asked Answered
C

2

7

The following GCC inline asm is taken from LuaJit's coco library. Can someone provide a line by line explanation of what it does?

static inline void coco_switch(coco_ctx from, coco_ctx to)
{
  __asm__ __volatile__ (
    "movl $1f, (%0)\n\t" 
    "movl %%esp, 4(%0)\n\t" 
    "movl %%ebp, 8(%0)\n\t"
    "movl 8(%1), %%ebp\n\t" 
    "movl 4(%1), %%esp\n\t" 
    "jmp *(%1)\n" "1:\n"
    : "+S" (from), "+D" (to) : : "eax", "ebx", "ecx", "edx", "memory", "cc");
}

Thanks

Carport answered 3/9, 2009 at 5:24 Comment(0)
R
11

My ASM is a bit fuzzy about the details, but I think I can give you a general idea.

ESP: Stack pointer, EBP: Base pointer.

movl $1f, (%0)

Move address of label 1 (defined on last line) into parameter 0 (from).

movl %%esp, 4(%0)

Move the content of register ESP into (from + 4).

movl %%ebp, 8(%0)

Move the content of register EBP into (from + 8).

movl 8(%1), %%ebp

Move the content of (to + 8) into register EBP.

movl 4(%1), %%esp

Move the content of (to + 4) into register ESP.

jmp *(%1)

Jump to address contained in (to).

The "1:" is a jump label.

"+S" declares a "source" (read) parameter, "+D" a destination (write) parameter. The list of registers at the end of the statement is the "clobber" list, a list of registers possibly modified by the ASM code, so the compiler can take steps to maintain consistency (i.e., not relying on e.g. ECX still containing the same value as before).

I guess that coco_ctx means "coco context". So: The function saves the current stack frame in the "from" structure, and sets the stack frame to what's saved in the "to" structure. Basically, it jumps from the current function into another function.

Radiosonde answered 3/9, 2009 at 6:28 Comment(6)
That's exactly right. It's not just jumping from one function to another, though: it's jumping from one entire call stack to another; it's totally switching execution contexts. (Also, gosh but GCC inline assembly syntax is bizarre.)Intransigeance
It's AT&T syntax (wiki.osdev.org/Opcode_syntax) wrapped in a C function-call-like syntax (wiki.osdev.org/Inline_Assembly). You won't believe it but I actually prefer it over the "standard" Intel syntax. ;-)Radiosonde
Does the context switch also work for C++ or do I have to write some different for thiscall?Carport
This way of context switching should work for all languages compiled to machine code and using identical calling conventions. This is definitely not my best field of knowledge, but it should work for C++ as well.Radiosonde
This ought to work for any x86 program that uses any normal calling convention (eg, cdecl, syscall, stdcall, pascal, etc...). That's the beauty of assembly; it is the lingua franca to all programming languages. The one thing to be careful of is that the contents of EAX, EBX, ECX, and EDX that came in from the caller ought to be restored, but I think that the compiler will take care of that automatically (since it basically has to do that for every function call anyway).Intransigeance
I think that the first line might be wrong. $1f probably is the address of the next label called "1" in "forward" direction (see #3898935).Ratline
I
2

DevSolar has the right answer -- I'll just add that you can learn a little more about what EBP and ESP are for here.

Intransigeance answered 3/9, 2009 at 6:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.