2011-11-11 115 views
2

以下代码与标志Od,O1一起按预期工作,但与O2,Ox失败。任何想法为什么?编译器标志更改代码行为(O2,Ox)

编辑:通过“失败”我的意思是,该函数什么都不做,似乎只是返回。

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调整了堆栈指针之后,它不能正确执行此操作 - 它不希望堆栈指针发生更改。

要解决这个问题,你不应该把所有C代码的那些asm语句之后,直到堆栈指针已经被正确还原:一切从第一pushadpopadstartThread()应该在汇编。这样,您可以加载本地变量的地址,并确保访问正确完成。

+0

我试图让所有的程序集在一个程序块中执行,但并不能帮助解决问题。 – aCuria

2

在使用内联汇编程序时,您可能想要了解在使用各种-Ox选项编译代码时是如何(或者是否)真正修改的代码。试试这个在您的二进制文件:

objdump -s your_program 

它提供的代码堆,但找到相应的代码段不应该是硬(搜索您的组装或函数名)。

顺便说一句,我被教导说重型优化在内联汇编方面做得不好,所以我倾向于将汇编程序例程分离为.S文件。