【问题标题】:Explanation of Asm codeAsm代码说明
【发布时间】:2010-11-25 04:28:18
【问题描述】:

以下 GCC 内联汇编取自 LuaJit 的 coco 库。有人可以逐行解释它的作用吗?

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");
}

谢谢

【问题讨论】:

    标签: gcc assembly lua x86 inline-assembly


    【解决方案1】:

    我的 ASM 对细节有点模糊,但我想我可以给你一个大致的概念。

    ESP:堆栈指针,EBP:基指针。

    movl $1f, (%0)
    

    将标签 1(在最后一行定义)的地址移动到参数 0(来自)。

    movl %%esp, 4(%0)
    

    将寄存器 ESP 的内容移入 (from + 4)。

    movl %%ebp, 8(%0)
    

    将寄存器EBP的内容移入(from + 8)。

    movl 8(%1), %%ebp
    

    将 (to + 8) 的内容移入寄存器 EBP。

    movl 4(%1), %%esp
    

    将 (to + 4) 的内容移动到寄存器 ESP 中。

    jmp *(%1)
    

    跳转到 (to) 中包含的地址。

    “1:”是跳转标签。

    “+S”声明一个“源”(读)参数,“+D”一个目的(写)参数。语句末尾的寄存器列表是“clobber”列表,一个可能被 ASM 代码修改的寄存器列表,因此编译器可以采取措施保持一致性(即,不依赖于仍然包含相同值的 ECX和以前一样)。

    我猜 coco_ctx 的意思是“可可上下文”。所以:该函数将当前堆栈帧保存在“from”结构中,并将堆栈帧设置为保存在“to”结构中的内容。基本上就是从当前函数跳转到另一个函数。

    【讨论】:

    • 完全正确。但是,这不仅仅是从一个函数跳转到另一个函数:它是从一个完整的调用堆栈跳转到另一个;它完全在切换执行上下文。 (另外,天哪,但 GCC 内联汇编语法很奇怪。)
    • 这是 AT&T 语法 (wiki.osdev.org/Opcode_syntax) 封装在 C 函数调用式语法 (wiki.osdev.org/Inline_Assembly) 中。你不会相信它,但我实际上更喜欢它而不是“标准”英特尔语法。 ;-)
    • 上下文切换是否也适用于 C++,还是我必须为 thiscall 编写一些不同的代码?
    • 这种上下文切换方式应该适用于编译为机器代码并使用相同调用约定的所有语言。这绝对不是我最擅长的知识领域,但它应该也适用于 C++。
    • 我认为第一行可能是错误的。 $1f 可能是在“正向”方向上称为“1”的下一个标签的地址(参见stackoverflow.com/questions/3898435/…)。
    【解决方案2】:

    DevSolar 有正确的答案 - 我只是补充一点,您可以了解更多关于 here. 的 EBP 和 ESP 的信息

    【讨论】:

      猜你喜欢
      • 2012-06-25
      • 2013-09-12
      • 2017-01-23
      • 2014-09-21
      • 2016-06-01
      • 2015-01-13
      • 2015-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多