EDN Admin
Well-known member
Not sure whether this is the right place to ask this, but Im trying to implement software context switching and Im running into problems. Basically, I allocate a stack for each thread, and then I use a scheduler to switch between the threads. It is
almost working in that it actually calls into the specified start function, but I have a situation where the EBP register is off by 4 and I cant figure out how to solve it.
This is how I set up the "main thread":
<div style="color:black; background-color:white
<pre><span style="color:blue void NativePlatform::StartMainThread(RuntimeThread* pThread, <span style="color:blue void* pData, <span style="color:blue void* startAddress)
{
<span style="color:blue void* stack = pThread->NativeStack;
__asm
{
mov eax, pThread
mov ebx, pData
mov ecx, startAddress
mov esi, ebp
mov edi, esp
mov ebp, stack
mov esp, ebp
push esi
push edi
push ebx
push eax
call ecx
pop eax
pop ebx
pop edi
pop esi
mov esp, edi
mov ebp, esi
}
}
[/code]
<br/>
The above works fine and I can call into the start function without any problems.
This is how I set up any additional threads:
<div style="color:black; background-color:white
<pre><span style="color:blue void NativePlatform::InitializeThreadContext(RuntimeThread* pThread, VirtualObject** pData)
{
<span style="color:blue void* stack = pThread->NativeStack;
<span style="color:blue void* startAddress = pThread->GetStartAddress();
__asm
{
mov ecx, esp
mov eax, pThread
mov esi, startAddress
mov esp, stack
push eax
push esi
mov eax, esp
push eax
<span style="color:green // Save registers
xor eax, eax
push eax
push eax
push eax
mov edi, esp
mov esp, ecx
mov stack, edi<br/> }
<span style="color:green // Save the stack for later<br/> pThread->CurrentStack = stack;
}
[/code]
And this is how I initiate a context switch:
<div style="color:black; background-color:white
<pre>__declspec(<span style="color:blue naked) <span style="color:blue void __fastcall NativePlatformSwitchContext(<span style="color:blue void* pOldStack, <span style="color:blue void* pNewStack)
{
__asm
{
<span style="color:green // Save registers
push ebp
push ebx
push esi
push edi
<span style="color:green // Save old stack
mov [ecx], esp <span style="color:green // store to pOldStack
<span style="color:green // Load new stack
mov esp, [edx] <span style="color:green // load from pNewStack
<span style="color:green // Restore registers
pop edi
pop esi
pop ebx
pop ebp
ret
}
}
[/code]
This almost works. The target function is called as expected, but the stack is not correct. What I found is that as soon as the destination function enters, and I manually subtract 4 from EBP, the stack is set up properly and the function can access all
of its parameters.
So the question is, how can I fix this off-by-4 problem?
<br/>
View the full article
almost working in that it actually calls into the specified start function, but I have a situation where the EBP register is off by 4 and I cant figure out how to solve it.
This is how I set up the "main thread":
<div style="color:black; background-color:white
<pre><span style="color:blue void NativePlatform::StartMainThread(RuntimeThread* pThread, <span style="color:blue void* pData, <span style="color:blue void* startAddress)
{
<span style="color:blue void* stack = pThread->NativeStack;
__asm
{
mov eax, pThread
mov ebx, pData
mov ecx, startAddress
mov esi, ebp
mov edi, esp
mov ebp, stack
mov esp, ebp
push esi
push edi
push ebx
push eax
call ecx
pop eax
pop ebx
pop edi
pop esi
mov esp, edi
mov ebp, esi
}
}
[/code]
<br/>
The above works fine and I can call into the start function without any problems.
This is how I set up any additional threads:
<div style="color:black; background-color:white
<pre><span style="color:blue void NativePlatform::InitializeThreadContext(RuntimeThread* pThread, VirtualObject** pData)
{
<span style="color:blue void* stack = pThread->NativeStack;
<span style="color:blue void* startAddress = pThread->GetStartAddress();
__asm
{
mov ecx, esp
mov eax, pThread
mov esi, startAddress
mov esp, stack
push eax
push esi
mov eax, esp
push eax
<span style="color:green // Save registers
xor eax, eax
push eax
push eax
push eax
mov edi, esp
mov esp, ecx
mov stack, edi<br/> }
<span style="color:green // Save the stack for later<br/> pThread->CurrentStack = stack;
}
[/code]
And this is how I initiate a context switch:
<div style="color:black; background-color:white
<pre>__declspec(<span style="color:blue naked) <span style="color:blue void __fastcall NativePlatformSwitchContext(<span style="color:blue void* pOldStack, <span style="color:blue void* pNewStack)
{
__asm
{
<span style="color:green // Save registers
push ebp
push ebx
push esi
push edi
<span style="color:green // Save old stack
mov [ecx], esp <span style="color:green // store to pOldStack
<span style="color:green // Load new stack
mov esp, [edx] <span style="color:green // load from pNewStack
<span style="color:green // Restore registers
pop edi
pop esi
pop ebx
pop ebp
ret
}
}
[/code]
This almost works. The target function is called as expected, but the stack is not correct. What I found is that as soon as the destination function enters, and I manually subtract 4 from EBP, the stack is set up properly and the function can access all
of its parameters.
So the question is, how can I fix this off-by-4 problem?
<br/>
View the full article