线程-线程调用1

前言

上一节我们分析了函数调用主要是将rbp(栈基址寄存器)压栈最后函数退出后将其弹栈实现调用和恢复现场. 而本节我们再接再厉接着分析线程调用的过程.

几个寄存器

在我们写代码之前要先对基本的寄存器有一个了解, 毕竟待会我们会先写一段汇编代码, 所以必须对寄存器要有一个简单的了解.

  1. rsp : 栈顶寄存器. 它始终指向一个栈的顶部.
  2. rbp : 栈基址寄存器. 它是同rsp寄存器连用的, 因为rsp会经常改变, 为了让编译器知道该栈的位置的地址就是用rbp来保存栈顶, 所以, 每个函数在开始时都要保存原来的rbp,设置自己的堆栈地址, 在函数结束返回时恢复原来的rbp,让上级函数可以正常使用rbp.
  3. edi, esi : 变址寄存器. 它们主要用于存放存储单元在段内的偏移量.
  4. ax, bx, cx, dx : 基本寄存器.
  5. ZF, CF等状态标志位 : 一般调用时使用pushflpopfl进行全部压栈和出栈.

对寄存器这样了解就行了, 毕竟我们不是讲解怎么学习汇编, 知道名字不陌生就行了.

线程调用

线程调用在调用时与函数调用基本一致, 调用时会将当前线程的所有的寄存器全部压栈, 再将切换线程的所有寄存器出栈就实现了一次线程的调用.

因为线程会不停的切换, 所以在写代码之前, 我们先确定用一个变量来保存当前线程, 我在这里用的变量名是current_thread.

  1. 我们先用汇编实现将寄存器全部压栈和全部出栈
.global switch_to	// 告诉编译器这是我们定义的函数
switch_to:	// 这是函数名
  push %ebp
  // 更改栈帧,用于寻参
  mov %esp, %ebp 

  // 保存现场 
  push %edi
  push %esi
  push %eax
  push %ebx
  push %ecx
  push %edx
  
  // 将所有状态标志位压栈
  pushfl

​ 以上我们就做完了压栈的操作了, 前面两步我们在分析函数调用时都见过了, 这里也是照搬过来的, 下面的都没有在函数调用中见过(但是这些操作确实也执行了只是我们看不到)但实际功能就是将寄存区压栈.

​ 明白了压栈那么出栈就简单了, 出栈与压栈的顺序相反.

  // 恢复现场, 顺序一定要正确
  popfl
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax
	popl %esi
	popl %edi

	popl %ebp
  ret
  1. current_thread变量保存当前线程

    前面说过我们需要知道究竟执行的是哪一个线程, 就定义了这个变量, 现在就在汇编中操作这个变量吧. 不过, 再此之前有一个要求, 我们需要对当前的线程传递一个参数, 还记得函数调用是怎么传递参数的吗? 如果不太清楚了可以在函数调用汇编中看看, 如果明白的话, 那么我们现在执行的方法也是一样的哦, 可以搬过来用就行了, 不过参数需要在下一节c语言中分析.

  // 切换栈 
  // 保存当前 esp
  mov current_thread, %eax 
  mov %esp, thread(,%eax,4)
  // 取下一个线程 id
  mov 8(%ebp), %eax 
  // 将 current_thread 重置为下一个线程
  mov %eax, current_thread 
  // 切换到下一个线程的栈 
  mov thread(,%eax,4), %esp

​ 我们先将现在线程的current_thread保存在eax寄存器中, 在切换线程后将eax保存在current_thread即可.

​ 但这里有一个thread变量之前没有说过我准备放在下一节讲完后自己分析它的作用.

  1. current_thread操作执行的位置

    上面我们分析了current_thread, 但是具体位置应该在压栈还是存栈还是中间呢?

    分析过函数调用应该很容易就知道, 压栈和出栈是函数(线程)所有操作之前和之后, 所以上面的操作肯定放在压栈后出栈前.

小结

本小结我们分析了用汇编实现线程的切换, 虽然汇编大多数人不怎么接受, 但这样的汇编量非常少, 逻辑也相当的简单, 相信都容易理解的. 线程的调用方式与函数调用的方式都是一样的.

你会发现这节写的代码并不能执行啊, 怎么运行啊? 而且后面我们还要写汇编? 后面我们基本不写汇编了, 只写c语言. 那么怎么用c语言来实现线程切换呢? 这就是我们下一节所要讲解的.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值