繁体   English   中英

C,内联汇编-mov指令段错误

[英]C,inline assembly - mov instruction segfaults

我们正在尝试实现某种“光纤”,并且现在希望为每个分配在堆上的“堆栈”,比如说固定大小约为2MB。

//2MB ~ 2^21 B = 2097152 B
#define FIB_STACK_SIZE 2097152

#define reg_t uint32_t

typedef struct fiber fiber;
struct fiber{
    ...
    //fiber's stack
    reg_t esp;
    ...
};

在创建光纤的过程中,我们分配该“堆栈”,并将创建的结构排队,以供以后在就绪队列中使用。

void fib_create(...){
    //fiber struct itself
    f = malloc(sizeof(*f)); //f later enqueued
    ...     
    //fiber stack
    f->stack = malloc(FIB_STACK_SIZE);
    f->esp = (reg_t)f->stack;
    ...
}

fib是从就绪队列中获取的结构,我们需要为其还原上下文。

显然,我们首先需要恢复堆栈指针s.th。 我们可以还原其他所有内容:

void fib_resume(){
    //assumes `fib' holds fiber to resume execution

    //restore stack pointers
    __asm__(
        "movl %0, %%esp;"
        :
        :"rm"(fib->esp)
        );

    ...
}

但是,该移动指令将导致段错误。 为什么? 而我们该如何规避呢?

在i386上(从内联汇编程序可以很明显地看出),堆栈逐渐变小。 这意味着将地址移到较低的地址,因此函数调用将减少堆栈地址。

这意味着当我们为线程/进程/等分配堆栈时。 通常的做法是将堆栈指针寄存器指向已分配内存的末尾。

在您的情况下,应为:

f->esp = (reg_t)f->stack + FIB_STACK_SIZE;

我仍然不确定在C函数中使用内联汇编程序来执行此操作,而不是在汇编器中完全编写该功能,这是否是一个好主意,但这应该可以解决当前的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM