【问题标题】:Inline Aseembly What do I do about an "Illegal instruction (core dumped)"内联汇编如何处理“非法指令(核心转储)”
【发布时间】:2012-09-16 21:31:08
【问题描述】:

下面的内联汇编代码有什么问题吗? 我在运行函数 spinlock_lock 时遇到“非法指令(核心转储)”。

void spinlock_lock(struct spinlock * lock) {

    int a;
    __asm__ __volatile__("movl %0, %%eax;"
                         "test %%eax, %%eax;"
                         "jnz spinlock_lock;"
                         :"=r"(a)
                         :"r"(lock->cmos_lock)
                         :"eax");

    __asm__ __volatile__ ("lock; cmpxchg %%edx, %0\n"
                          :"=r"(a)
                          :"r"(lock->cmos_lock)
                          :"edx", "memory");

【问题讨论】:

    标签: inline inline-assembly


    【解决方案1】:

    问题是你的分支;通常 (x86) the called function will save the frame pointer on the stack before executing any other code

    您的jnz spinlock_lock 分支将分支回整个函数的入口点,从而在返回内联汇编程序之前再次保存帧指针。保存帧指针足够的时间,你会用完堆栈。更不用说如果你离开你的内联汇编器并在它之外进行分支,你的寄存器可能不再包含你认为它们所做的事情。

    您可能应该在您的内联汇编器中放置一个标签,然后返回到该标签。

    此外,指令cmpxchg %edx, %0 可以对寄存器进行操作,但不能与lock 结合使用,因为您使用的是寄存器操作数。要使lock cmpxchg 工作,您需要将匹配参数约束从r 更改为m

    您可能需要查看here 以了解需要内存操作数的lock cmpxchg 的讨论,或查看here 以了解无需汇编程序的自旋锁的替代 gcc 实现。

    【讨论】:

    • 你在说他的?__asm__ __volatile__("L:" "movl %0, %%eax;" "test %%eax, %%eax;" // "jnz spinlock_lock;" " jnz L;" ://"=r"(a) :"r"(lock->cmos_lock) :"eax");
    • @dykw 是的,您的 jnz 将分支回函数入口点,您应该将分支保留在您的内联汇编代码中。
    • 它不起作用。我尝试评论“asm volatile ("lock; cmpxchg %%edx, %0\n""。非法指令消失了。为什么?
    • @dykw 在答案中添加了一些细节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多