线程切换过程:
interrupt_handler.S(interrupt_handle_entry) -> interrupt.c(c_version_handle) -> switch_to.S
结论:
在switch_to函数中必须保存esi/edi/edx/ebp这四个寄存器
原因:
GCC在对C、汇编代码进行混合编译时,遵从cdecl调用约定,且cdecl规定EBX, EBP, ESP, EDI, ESI, CS, DS这些寄存器不应该受到函数调用影响。而汇编写的switch_to函数是受到c语言写的c_version_handle函数的调用。所以在switch_to中应该保存这些寄存器。在实际场景中CS、DS、ESP不会变化,所以就不用保存这些寄存器。
疑问:
问:在switch_to汇编代码中没有修改这四个寄存器的代码为什么还要保存这四个寄存器?
答:
switch_to函数负责切换线程,A线程进入c_version_handle并使用了这四个寄存器,然后switch_to到B线程去执行,如果B线程修改了这四个寄存器,当A线程又调度上来以后,A线程的这四个寄存器值就丢失了。
问:在c_version_handle函数执行了switch_to以后就结束了,最后也没有用这四个寄存器,为什么还要保存这四个寄存器?
从c代码上看,执行完switch_to以后没有其他的代码,把该文件编译成汇编再看下:
在调用完switch_to以后会执行一个leave汇编命令,leave命令在32位汇编下相当于:
mov esp,ebp;
pop ebp
所以这里会使用到ebp寄存器,所以必须要保存这个寄存器。