以下代码按预期使用标记Od,O1,但在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 :(得分:3)
可能是因为你的编译器没有在更高的优化级别上使用特定的帧指针寄存器,从而释放了一个额外的通用寄存器。
这意味着编译器使用堆栈指针的偏移量访问局部变量pStack
。在pushad
和pushfd
调整堆栈指针后,它无法正确执行此操作 - 它不会期望堆栈指针发生更改。
为了解决这个问题,你不应该在那些asm
语句之后放置任何C代码,直到堆栈指针被正确恢复为止:从第一个pushad
到popad
的所有内容或startThread()
应该是汇编程序。这样,您可以加载局部变量的地址,并确保正确完成访问。
答案 1 :(得分:2)
当您使用内联汇编程序时,您可能希望看到在使用各种-Ox选项编译时代码是如何(或是否)真正修改的。在你的二进制文件上试试这个:
objdump -s your_program
它提供了一堆代码,但找到相应的代码部分应该不那么难(搜索程序集或函数名称)。
顺便说一下,我被告知重度优化对内联汇编不是很好,所以我倾向于将汇编程序例程分离为.S文件。