之前因为工作忙,好长时间没更了。
这次把进程切换里面的寄存器上下文切换详细的说一下吧。感觉有必要
先码几行代码,这样好说
// 任务的寄存器上下文数据结构
/*
* 在内存里面的数据结构为
* 0x00000000 [eip]
* 0x00000004 [esp]
* 0x00000008 [ebx]
* 0x00000012 [ecx]
* 0x00000016 [edx]
* 0x00000020 [esi]
* 0x00000024 [edi]
* 0x00000028 [ebp]
*/
/*
* 在C里面的定义为
*/
struct context{
uint eip;
uint esp;
uint ebx;
uint ecx;
uint edx;
uint esi;
uint edi;
uint ebp;
};
// 这个是任务0的上下文
struct context task0_con;
void task0()
{
// 这个代表由任务0切换到任务1
swtch(&task0_con, &task1_con);
}
// 这个是任务1的上下文
struct context task1_con;
void task1()
{
// 由任务1切换到任务0
swtch(&task1_con, &task0_con);
}
swtch:
mov eax, dword [esp + 4]
pop dword [eax]
mov dword [eax + 4], esp
mov dword [eax + 8], ebx
mov dword [eax + 12], ecx
mov dword [eax + 16], edx
mov dword [eax + 20], esi
mov dword [eax + 24], edi
mov dword [eax + 28], ebp
mov eax, dword [esp + 4]
mov ebp, dword [eax + 28]
mov edi, dword [eax + 24]
mov esi, dword [eax + 20]
mov edx, dword [eax + 16]
mov ecx, dword [eax + 12]
mov ebx, dword [eax + 8]
mov esp, dword [eax + 4]
push dword [eax]
ret
下面就模拟一遍吧,
假设当前CPU运行的是任务0(task0):
在调用swtch之前,其堆栈为
task0_stack:
0x00000400 [0xFFFFFFF0] ; 0xFFFFFFF0就用来表示任务0(task0)的栈底了
当调用swtch后,其堆栈为
task0_stack (swtch start):
0x000003F4 [task0 的返回地址]
0x000003F8 [task0_con] ; 这里的task0_con指的是地址
0x000003FC [task1_con] ; 这里的task1_con指的是地址
0x00000400 [0xFFFFFFF0]
swtch:
将 esp + 4中的内容赋值给eax,即 eax <= &task0_con;
然后把“task0 的返回地址”弹出堆栈,赋值给 dword [eax],即 task0_con.eip = task0 的返回地址
之后分别吧esp, ebx, ecx, edx, esi, edi, ebp 赋值给 task0_con 中的对应项
赋值完毕之后,也就是CPU执行完swtch的第 10行,
mov dword [eax + 28], ebp
其堆栈为
task0_stack:
0x000003F8 [task0_con] ; 这里的task0_con指的是地址
0x000003FC [task1_con] ; 这里的task1_con指的是地址
0x00000400 [0xFFFFFFF0]
然后把 esp + 4 中的内容赋值给eax,即 eax = &task1_con
之后赋值寄存器,和上面的操作差不多,不过这次是把task1_con中对应寄存器的值赋值给cpu的寄存器中
最后把task1_con.eip压入堆栈,也就是把任务1的返回地址压入堆栈,其堆栈结构为(压栈这一行上面已经把栈顶改为任务1的了,"mov esp, dword [eax + 4]")
task1_stack:
0x000007FC [task1 的返回地址]
0x00000800 [0xFFFFFFF1] ; 0xFFFFFFF1就用来表示任务1(task1)的栈底了
然后ret之后就返回到任务1中执行了,
之后调用swtch时和上面所说的步骤一样,只是切换的方式相反了,由任务1切换到任务0
当然大家也可以在 struct context中加上elfags寄存器,这样就更完美了。