Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Segfault内联汇编_C_Assembly_Inline Assembly - Fatal编程技术网

C Segfault内联汇编

C Segfault内联汇编,c,assembly,inline-assembly,C,Assembly,Inline Assembly,我试图创建一个基于off的绿色线程实现,但是我的switch函数给了我一个segfault,因为加载寄存器的代码没有在函数的末尾运行。这是我的密码: void ThreadSwitch(Thread in, Thread out) { if (!out && !in) { return; } if (out) { // save registers for out } if (in) {

我试图创建一个基于off的绿色线程实现,但是我的switch函数给了我一个segfault,因为加载寄存器的代码没有在函数的末尾运行。这是我的密码:

void ThreadSwitch(Thread in, Thread out) {
    if (!out && !in) {
            return;
    }
    if (out) {
        // save registers for out    
    }
    if (in) {
        SetCurrentThread(in);
        mtx_lock(&in->mutex);
        uint64_t rsp = in->cpu.rsp;
        uint64_t r15 = in->cpu.r15;
        uint64_t r14 = in->cpu.r14;
        uint64_t r13 = in->cpu.r13;
        uint64_t r12 = in->cpu.r12;
        uint64_t rbx = in->cpu.rbx;
        uint64_t rbp = in->cpu.rbp;
        mtx_unlock(&in->mutex);
        asm volatile("mov %[rsp], %%rsp\n"
                     "mov %[r15], %%r15\n"
                     "mov %[r14], %%r14\n"
                     "mov %[r13], %%r13\n"
                     "mov %[r12], %%r12\n"
                     "mov %[rbx], %%rbx\n"
                     "mov %[rbp], %%rbp\n" : : [rsp] "r"(rsp), [r15] "r"(r15), [r14] "r"(r14), [r13] "r"(r13), [r12] "r"(r12), [rbx] "r"(rbx), [rbp] "r"(rbp));
    }
}
Xcode说内联程序集导致了segfault,但我的lldb反汇编看起来是这样的(您可以忽略其中的95%,只是提供给上下文):

segfault发生在它试图访问堆栈上的内容时,这是有意义的,因为它刚刚关闭了堆栈。但是为什么编译器要插入这个呢?编译器还将%eax存储在堆栈0x1000f892b处。编译器正在打开一个寄存器吗?因为它在内联asm中不使用%rax。有解决办法吗

这是在OSX 10.10.2上使用苹果LLVM 6.0版(clang-600.0.57),如果有帮助的话


提前感谢。

我强烈建议您不要编写依赖于未定义行为的程序

不允许跳入和跳出内联程序集,因为编译器无法分析它不知道的控制流,在创建线程时,您从任何地方跳入asm语句,然后离开它。为了避免这些隐式跳转,您需要在同一asm语句中保存和恢复包括%rip在内的寄存器

对于线程切换例程,asm语句更改的所有寄存器都必须列为输出或关闭寄存器,该线程切换例程是所有值未保存的寄存器,因为它们被其他线程更改。如果不这样做,编译器将错误地认为它们没有被修改

asm语句在使用之前必须避免覆盖其输入,在代码中没有任何内容禁止编译器将变量r12存储在寄存器%r14中

你的锁不是没有意义就是不够用


完全在汇编中编写函数要简单得多,就像您引用的教程一样

编译器在
eax
上做了什么并不明显(可能禁用了优化?),但是地址
-0x58(%rbp)
应该是有效的,因为您要切换回一个线程,该线程本身执行先前设置
%rbp
的代码。我将尝试确保禁用优化(我正在使用CMake的调试设置),但此代码在线程第一次运行时失败。线程上的堆栈已设置为使此函数(ThreadSwitch)返回到线程的目标函数中。将此函数标记为“裸”可能是合理的,所以编译器不会在函数体(序言和尾声)前后生成堆栈帧指令对于这一点,可能CLang guys将其添加为向后兼容。但这也会使您难以使用局部变量,因为您没有更改堆栈指针,并且会覆盖调用方变量。
   0x1000f88b4:  movq   -0x8(%rbp), %rdi
   0x1000f88b8:  callq  0x1000f83a0               ; SetCurrentThread at thread.cc:21
   0x1000f88bd:  movq   -0x8(%rbp), %rdi
   0x1000f88c1:  addq   $0x50, %rdi
   0x1000f88c8:  callq  0x1000f7b80               ; mtx_lock at tct.c:106
   0x1000f88cd:  movq   -0x8(%rbp), %rdi
   0x1000f88d1:  movq   (%rdi), %rdi
   0x1000f88d4:  movq   %rdi, -0x18(%rbp)
   0x1000f88d8:  movq   -0x8(%rbp), %rdi
   0x1000f88dc:  movq   0x8(%rdi), %rdi
   0x1000f88e0:  movq   %rdi, -0x20(%rbp)
   0x1000f88e4:  movq   -0x8(%rbp), %rdi
   0x1000f88e8:  movq   0x10(%rdi), %rdi
   0x1000f88ec:  movq   %rdi, -0x28(%rbp)
   0x1000f88f0:  movq   -0x8(%rbp), %rdi
   0x1000f88f4:  movq   0x18(%rdi), %rdi
   0x1000f88f8:  movq   %rdi, -0x30(%rbp)
   0x1000f88fc:  movq   -0x8(%rbp), %rdi
   0x1000f8900:  movq   0x20(%rdi), %rdi
   0x1000f8904:  movq   %rdi, -0x38(%rbp)
   0x1000f8908:  movq   -0x8(%rbp), %rdi
   0x1000f890c:  movq   0x28(%rdi), %rdi
   0x1000f8910:  movq   %rdi, -0x40(%rbp)
   0x1000f8914:  movq   -0x8(%rbp), %rdi
   0x1000f8918:  movq   0x30(%rdi), %rdi
   0x1000f891c:  movq   %rdi, -0x48(%rbp)
   0x1000f8920:  movq   -0x8(%rbp), %rdi
   0x1000f8924:  addq   $0x50, %rdi
   0x1000f892b:  movl   %eax, -0x54(%rbp)
   0x1000f892e:  callq  0x1000f7de0               ; mtx_unlock at tct.c:264
   0x1000f8933:  movq   -0x18(%rbp), %rdi         ; beginning of inline asm 
   0x1000f8937:  movq   -0x20(%rbp), %rcx
   0x1000f893b:  movq   -0x28(%rbp), %rdx
   0x1000f893f:  movq   -0x30(%rbp), %rsi
   0x1000f8943:  movq   -0x38(%rbp), %r8
   0x1000f8947:  movq   -0x40(%rbp), %r9
   0x1000f894b:  movq   -0x48(%rbp), %r10
   0x1000f894f:  movq   %rdi, %rsp
   0x1000f8952:  movq   %rcx, %r15
   0x1000f8955:  movq   %rdx, %r14
   0x1000f8958:  movq   %rsi, %r13
   0x1000f895b:  movq   %r8, %r12
   0x1000f895e:  movq   %r9, %rbx
   0x1000f8961:  movq   %r10, %rbp                ; end of inline asm
-> 0x1000f8964:  movl   %eax, -0x58(%rbp)
   0x1000f8967:  addq   $0x60, %rsp
   0x1000f896b:  popq   %rbp
   0x1000f896c:  retq