Linux内核学习笔记知识点杂烩(二)
冯诺依曼结构:冯诺依曼结构就是存储结构计算机。
存储结构计算机:
硬件上的解释:IP(16位机)/EIP(32位机)/RIP(64位机):Instruction Pointer,CPU的寄存器,总是指向内存的某个区域。使用IP来不断的从内存中获得指令执行
- 程序员思维:
CPU在实际取指令时根据cs:ep来准确定位一个指令(cs+eip),cs是code segment Register,代码段寄存器。eip指明代码段的地址。
AT&T汇编格式与lnte汇编格式略有不同,Linux内核使用的是AT&T汇编格式
函数调用汇编解释:
call 0x12345:
- push %eip(*) //把当前指令指针eip压栈
- movl $0x12345, %eip(*) //给eip赋予新值
ret:return
- popl %eip(*)
注意:eip寄存器不能被直接修改,只能通过特殊指令(call or return etc)间接修改。
esp栈顶指针,ebp栈底指针。栈顶和栈底都是相对的。函数调用堆栈是由逻辑上多个堆栈叠加起来的。函数的返回值默认使用eax寄存器存储返回给上一级函数。eax存储了默认的返回值。
把c程序反汇编之后,所有以
'.'
开头的均是用于链接时的辅助信息,去掉之后得到干净的汇编代码。
enter和leave是宏指令,enter是把栈置空,leave是撤销函数调用堆栈。
enter是建立框架的命令:
- push %ebp //建立堆栈
- mov %esp, %ebp //把栈顶指针移向当前堆栈
leave是拆除框架的命令:
- mov %ebp, %esp //清空堆栈
- pop %ebp //恢复到原来的堆栈中
- ret
计算机三大法宝:
- 存储程序计算机
- 函数调用堆栈
- 中断机制
OS的“两把剑”:中断上下文和进程上下文切换。
堆栈是C语言程序运行时必须的一个记录调用路径和參数的空间
- 函数调用框架
- 传递参数
- 保存返回地址
- 提供局部变量空间
- 等等
C语言编译器对堆栈的使用有一套的规则。
eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。
esp是栈顶指针,ebp是基址指针,eax是(针对操作数和结果数据的)累加器 ,返回函数结果,返回函数调用的默认值。-cs:eip:总是指向下一条的指令地址:
- 顺序执行:总是指向地址连续的下一条指令
- 跳转/分支:执行这样的指令的时候,cs:eip的值会根据程序需要被修改
- call:将当前cs:eip的值压入栈顶(当前下一条执行的地址A),cs:eip指向被调用函数的入口地址
- ret:从栈顶弹出原来保存在这里的cs:eip的值(地址A),放入cs:eip中
中断:
引入中断之后便有了多道程序设计,可以跑多个程序。每个程序都有自己的执行流,执行流是如何进行切换的呢?
当一个中断信号发生的时候,cpu把当前的eip、esp、ebp都压到内核堆栈中,再把eip指向中断处理程序的入口,进行保存现场,执行中断处理程序。
C语言内嵌汇编语法:
即格式为asm(" statements'": output regs: Input regs: clobbered regs);
__asm__( 汇编语句模板: 输出部分 输入部分 破坏描述部分);