簡體   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