1. 何时需要切换栈:
上下文切换,如:
当需要切换进程时,需要保存正在运行的进程并切换到新的进程。
当从一个函数切换到另一个函数时,需要保存原有的栈寄存器
2. 切换栈需要有哪些基本操作:
1. 切换进程时,什么可以表示一个正在运行的程序?
程序中各个寄存器的值表示程序的运行状态。
其中ESP和EBP表示栈指针。ESP是当前运行的栈指针,EBP表示进程初始化时的栈指针。
2. call convention:
in X86, 在调用子函数时,IA32 and X64 有不同的参数传递规则。参考x86 calling conventions - Wikipedia
3. 示例演示:
主要流程如下:
switch: save all old process's register load new process's register load new process's ESP->完成切换栈操作
3.1 操作系统导论:Chapter 6
对于xv6中的进程切换代码函数定义如下:
其中struct context是进程上下文数据,有[context ptr, esp, ebx, ecx, edx, edi, esi, ebp]
void switch (struct context **old, struct context *new);
具体汇编代码:(使用的是IA32 的cdecl calling convention: "In cdecl, subroutine arguments are passed on the stack."即函数的参数从右往左一次存到ESP中)
xv6: switch:
# 4(%esp) save **old, 8(%esp) save *new # #save old context's registers: # #load old context ptr(*old) to eax movl 4(%esp), eax # save all old context's register popl 0(%eax) #eax[0](old[0]) save the old context ptr movl %esp, 4(%eax) movl %ebx, 8(%eax) movl %ecx, 12(%eax) movl %edx, 16(%eax) movl %esi, 20(%eax) movl %edi, 24(%eax) movl %ebp, 28(%eax) # #load new context's registers: # #load new context ptr movl 4(%esp), eax # load all new context's register movl 28(%eax), %ebp movl 24(%eax), %edi movl 20(%eax), %esi movl 16(%eax), %edx movl 12(%eax), %ecx movl 8(%eax), %ebx movl 4(%eax), %esp #new stack point has been set pushl 0(%eax) # return into new context ret
3.2 UEFI FSP SwitchStack
这里涉及到从CAR(cach as Ram)即TemporaryMemory搬到PermanentMemory的操作,
因此这个情况下,把栈空间原封不动的搬到PermanentMemoryBase对应的地方就好,操作如下:
NewRsp = OldRsp - TemporaryMemoryBase + PermanentMemoryBase
NewRbp = OldRbp - TemporaryMemoryBase + PermanentMemoryBase //新的Rbp就是旧的Rbp的一个fixup(从旧的memorybase 往新的memorybase般)
//其它的register复制到新的栈空间
下面分别是x64和IA32的示例:他们的calling convention 不一样(line38, line39)
3.2.1 x64 calling convention, rcx(1st parameter), rdx, r8, r9
15 ; VOID 16 ; EFIAPI 17 ; SecSwitchStack ( 18 ; UINT32 TemporaryMemoryBase, 19 ; UINT32 PermanentMemoryBase 20 ; ); 21 ;------------------------------------------------------------------------------ 22 global ASM_PFX(SecSwitchStack) 23 ASM_PFX(SecSwitchStack): 24 ; 25 ; Save four register: rax, rbx, rcx, rdx 26 ; 27 push rax 28 push rbx 29 push rcx 30 push rdx 31 32 ; 33 ; !!CAUTION!! this function address's is pushed into stack after 34 ; migration of whole temporary memory, so need save it to permanent 35 ; memory at first! 36 ; 37 38 mov rbx, rcx ; Save the first parameter rbx = rcx 39 mov rcx, rdx ; Save the second parameter 40 41 ; 42 ; Save this function's return address into permanent memory at first. 43 ; Then, Fixup the esp point to permanent memory 44 ; 45 mov rax, rsp 46 sub rax, rbx 47 add rax, rcx 48 mov rdx, qword [rsp] ; copy pushed register's value to permanent memory 49 mov qword [rax], rdx 50 mov rdx, qword [rsp + 8] 51 mov qword [rax + 8], rdx 52 mov rdx, qword [rsp + 16] 53 mov qword [rax + 16], rdx 54 mov rdx, qword [rsp + 24] 55 mov qword [rax + 24], rdx 56 mov rdx, qword [rsp + 32] ; Update this function's return address into permanent memory 57 mov qword [rax + 32], rdx 58 mov rsp, rax ; From now, rsp is pointed to permanent memory 59 60 ; 61 ; Fixup the rbp point to permanent memory 62 ; 63 mov rax, rbp 64 sub rax, rbx 65 add rax, rcx 66 mov rbp, rax ; From now, rbp is pointed to permanent memory 67 68 pop rdx 69 pop rcx 70 pop rbx 71 pop rax 72 ret
3.2.2 IA32 calling convention
15 ; VOID 16 ; EFIAPI 17 ; SecSwitchStack ( 18 ; UINT32 TemporaryMemoryBase, 19 ; UINT32 PermanentMemoryBase 20 ; ); 21 ;------------------------------------------------------------------------------ 22 global ASM_PFX(SecSwitchStack) 23 ASM_PFX(SecSwitchStack): 24 ; 25 ; Save four register: eax, ebx, ecx, edx 26 ; 27 push eax 28 push ebx 29 push ecx 30 push edx 31 32 ; 33 ; !!CAUTION!! this function address's is pushed into stack after 34 ; migration of whole temporary memory, so need save it to permanent 35 ; memory at first! 36 ; 37 38 mov ebx, [esp + 20] ; Save the first parameter 39 mov ecx, [esp + 24] ; Save the second parameter 40 41 ; 42 ; Save this function's return address into permanent memory at first. 43 ; Then, Fixup the esp point to permanent memory 44 ; 45 mov eax, esp 46 sub eax, ebx 47 add eax, ecx 48 mov edx, dword [esp] ; copy pushed register's value to permanent memory 49 mov dword [eax], edx 50 mov edx, dword [esp + 4] 51 mov dword [eax + 4], edx 52 mov edx, dword [esp + 8] 53 mov dword [eax + 8], edx 54 mov edx, dword [esp + 12] 55 mov dword [eax + 12], edx 56 mov edx, dword [esp + 16] ; Update this function's return address into permanent memory 57 mov dword [eax + 16], edx 58 mov esp, eax ; From now, esp is pointed to permanent memory 59 60 ; 61 ; Fixup the ebp point to permanent memory 62 ; 63 mov eax, ebp 64 sub eax, ebx 65 add eax, ecx 66 mov ebp, eax ; From now, ebp is pointed to permanent memory 67 68 pop edx 69 pop ecx 70 pop ebx 71 pop eax 72 ret 73
标签:movl,esp,mov,eax,切换,memory,操作,edx From: https://www.cnblogs.com/nipper/p/18118726