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

标签 c segmentation-fault stack inline-assembly

我们正在尝试实现某种“纤维”,并希望在堆上为每个“堆栈”分配一个“堆栈”,暂时假设大小接近 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 函数中使用内联汇编程序而不是完全用汇编程序编写函数是否是一个好主意,但这应该可以解决眼前的问题。

关于C、内联汇编-mov指令段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37159578/

相关文章:

符合 ANSI C 的实现是否可以在其标准库中包含其他函数?

c - 为什么提示我输入的次数比我预期的要多?

perl - 在 Perl 中调试段错误有哪些好的方法或步骤?

c - C 中反转字符串时出现段错误

java - ArrayList 初始大小不起作用

java - java中使用数组实现堆栈的切换情况

c - 在 sigaction 处理程序中使用 flock()

在cgi中调用路由-n

c - 初始化哈希表的问题

c - 使用节点实现堆栈,函数外部不知道顶部节点指针,顶部指针始终为 NULL