2016-05-05 4 views
2

私は "ファイバー"と呼ばれるものを実行するためにスケジューラーを作成しようとしています。 残念ながら、私は実際にインラインアセンブリを書くことに慣れていません。インラインアセンブリ - 不要な中間コピー命令

typedef struct { 
    //fiber's stack 
    long rsp; 
    long rbp; 

    //next fiber in ready list 
    struct fiber *next; 

} fiber; 

//currently executing fiber 
fiber *fib; 

だから、非常に最初の仕事は - 明らかに - それは一時停止できるようにmain機能のための繊維を作成します。

int main(int argc, char* argv[]){ 

    //create fiber for main function 
    fib = malloc(sizeof(*fib)); 
    __asm__(
     "movq %%rsp, %0;" 
     "movq %%rbp, %1;" 
     : "=r"(fib->rsp),"=r"(fib->rbp) 
     ); 

    //jump to actual main and execute 
    __asm__(...); 

} 

この

はなぜ、これが一時的なレジスタに mov Sをコンパイルん

movl $24, %edi #, 
    call malloc # 
#APP 
# 27 "scheduler.c" 1 
    movq %rsp, %rcx;movq %rbp, %rdx; # tmp92, tmp93 
# 0 "" 2 
#NO_APP 
    movq %rax, fib(%rip) # tmp91, fib 
    movq %rcx, (%rax) # tmp92, MEM[(struct fiber *)_3].rsp 
    movq %rdx, 8(%rax) # tmp93, MEM[(struct fiber *)_3].rbp 

にコンパイルされますか?どうにか私はそれらを取り除くことができますか?

この質問の最初のバージョンは、gcc -O0のasm出力を持っていましたが、さらに多くの命令と一時ファイルがありました。

最適化をオンにしても、それを取り除くことはできません。それらをオン

+0

あなたが最適化を可能にしましたか? – Jester

+0

@Jester私は最初はなかったが、それらをオンにしても一時的なものを取り除くことはできない(上記の編集を参照)。 – User1291

+0

Cは_methods_ – Olaf

答えて

3

は、それはいくつかの余分なロードとストアを取り除くでした一時

を取り除くしません。 fibは、あなたがグローバル変数として宣言して以来、もちろんメモリに残っています。 raxは、メモリ内のfibに割り当てる必要があるmallocからの戻り値です。他の2行はあなたのfibメンバーにも書き込みます。

レジスタ出力を指定したので、asmブロックはメモリに直接書き込むことができません。それはしかし、メモリの制約を修正するのは簡単です:

__asm__(
    "movq %%rsp, %0;" 
    "movq %%rbp, %1;" 
    : "=m"(fib->rsp),"=m"(fib->rbp) 
    ); 

これが生成されます:

call malloc 
    movq %rax, fib(%rip) 
    movq %rsp, (%rax) 
    movq %rbp, 8(%rax) 
+0

'' = rmコンパイラにオプションを与えることができます。この場合は問題にはなりませんが、それらの値を参照するコードを記述すると、コンパイラはそれらをregs店舗の荷物を運んでしまった。 (理想的には、C変数に命令を使わずに 'rbp'の値を参照させる方法があります)。複数オプションの制約があるとClangは時には貧弱な選択をするので、コードをチェックしてください。 (実際に、私はclangがGNU C 'asm'ステートメントでうまくいかなかったのを覚えていませんが、起こる可能性があります)。 –

関連する問題