2

次のコードは、フラグOd、O1では期待どおり動作しますが、O2、0xでは失敗します。なぜどんなアイデア?コンパイラフラグ変更コードの動作(O2、0x)

編集: "失敗"私は機能が何もせず、ちょうど戻っているようです。

の提案を実装した後
void thread_sleep() 
{ 
    listIterator nextThread = getNextThread(); 
    void * pStack = 0; 
    struct ProcessControlBlock * currPcb = pPCBs->getData(currentThread); 
    struct ProcessControlBlock * nextPcb = pPCBs->getData(nextThread); 

    if(currentThread == nextThread) 
    { 
     return; 
    } 
    else 
    { 
     currentThread = nextThread; 
     __asm pushad   // push general purpose registers 
     __asm pushfd   // push control registers 
     __asm mov pStack, esp // store stack pointer in temporary 

     currPcb->pStack = pStack; // store current stack pointer in pcb 
     pStack = nextPcb->pStack; // grab new stack pointer from pcb 

     if(nextPcb->state == RUNNING_STATE)// only pop if function was running before 
     { 
      __asm mov esp, pStack  // restore new stack pointer 
      __asm popfd 
      __asm popad; 
     } 
     else 
     { 
      __asm mov esp, pStack  // restore new stack pointer 
      startThread(currentThread); 
     } 
    } 
} 

//:(まだ動作しません)

listIterator nextThread = getNextThread(); 
struct ProcessControlBlock * currPcb = pPCBs->getData(currentThread); 
struct ProcessControlBlock * nextPcb = pPCBs->getData(nextThread); 
void * pStack = 0; 
void * pNewStack = nextPcb->pStack; // grab new stack pointer from pcb 
pgVoid2 = nextPcb->pStack; 

if(currentThread == nextThread) 
{ 
    return; 
} 
else 
{ 
    lastThread = currentThread; // global var 
    currentThread = nextThread; 


    if(nextPcb->state == RUNNING_STATE)// only pop if function was running before 
    { 
     __asm pushad    // push general purpose registers 
     __asm pushfd    // push control registers 
     __asm mov pgVoid1, esp  // store stack pointer in temporary 
     __asm mov esp, pgVoid2  // restore new stack pointer 
     __asm popfd 
     __asm popad; 

     { 
      struct ProcessControlBlock * pcb = pPCBs->getData(lastThread); 
      pcb->pStack = pgVoid1; // store old stack pointer in pcb 
     } 
    } 
    else 
    { 
     __asm pushad    // push general purpose registers 
     __asm pushfd    // push control registers 
     __asm mov pgVoid1, esp // store stack pointer in temporary 
     __asm mov esp, pgVoid2  // restore new stack pointer 

     { 
      struct ProcessControlBlock * pcb = pPCBs->getData(lastThread); 
      pcb->pStack = pgVoid1; // store old stack pointer in pcb 
     } 
     startThread(currentThread); 
    } 
} 
+0

"失敗"とは具体的にはどういう意味ですか? – Tudor

+0

別の最適化を適用すると表示される目に見えないバグがあります。 – starrify

+0

期待どおりに機能しません。この関数は呼び出されたときに別の「スレッド」をスケジュールすることになっています。 「失敗」とは、関数がまったく実行されずに即座に返される場合のように意味します。 – aCuria

答えて

3

コンパイラが解放され、より高い最適化レベルで特定のフレームポインタレジスタを使用していないので、それは可能性があります追加の汎用レジスタ。

これは、コンパイラがスタックポインタからのオフセットを使用してローカル変数pStackにアクセスすることを意味します。スタックポインターがpushadpushfdで調整された後、これを正しく実行することはできません。スタックポインターの変更は期待されていません。この問題を回避するには

スタックポインタが正しく復元されるまで、あなたは、これらのasm文の後に任意のCコードを置くべきではありません。最初のpushadからpopadまたはstartThread()にすべてが、アセンブラにする必要があります。このようにして、ローカル変数のアドレスをロードし、アクセスが正しく行われるようにすることができます。

+0

すべてのアセンブリを1つのブロックで実行しようとしましたが、状況には役立ちません。 – aCuria

2

インラインアセンブラを使用しているとき、さまざまな-Oxオプションでコンパイルされたときに実際にコードがどのように修正されているかを確認したいと思うでしょう。

objdump -s your_program 

は、それがコードのヒープを与えるが、対応するコードセクションを見つけることは難しい(あなたのアセンブリまたは関数名で検索)ということではありません:あなたのバイナリでこれを試してみてください。

ところで、重い最適化はインラインアセンブリではあまりうまくいかないと教えられました。そのため、アセンブラルーチンを.Sファイルに分割する傾向があります。

関連する問題