linux内核分析课程笔记(一)

冯诺依曼体系结构

冯诺依曼体系结构实际上就是存储程序计算机。

从两个层面来讲:

  • 从硬件的角度来看,冯诺依曼体系结构逻辑上可以抽象成CPU和内存,通过总线相连。CPU上有一些寄存器,IP(Instruction Pointer)是一个指针,总是指向内存的某一块区域CS(Code Segment),CPU即从IP指向的地址取一条指令进行执行,执行完之后IP自增1,加到下一条指令(逻辑意义上的1,因为有些指令系统是变长指令)

  • 从程序员的角度来看,存储程序计算机。CPU从程序员的角度可以抽象成一个无条件的for循环,总是执行下一条指令。

for(;;){
next instruction();
}

API(Application Program Interface)

ABI(Application Binary Interface)

32位的x86中EIP的三条特性:

  • 每条指令执行完成后EIP自加1
  • 指令的长度不同
  • EIP还可能会被一些指令修改,如:CALL、RET、JMP以及条件JUMP

x86汇编基础

x86寄存器

有8位、16位和32位的寄存器。

16位:AX、BX、CX、DX、BP、SI、DI、SP

32位:EAX(累加器)、EBX(基地址寄存器)、ECX(计数寄存器)、EDX(数据寄存器)、EBP(堆栈基址指针)、ESI与EDI(变址寄存器)、ESP(堆栈顶指针)

段寄存器:

  • CS(Code Segment Register),代码段
  • DS(Data Segment Register),数据段
  • ES(Extra Segment Register),附加数据段
  • SS(Stack Segment Register),堆栈段
  • FS与GS段寄存器用于区分x86的两种模式

CPU在实际取指令时根据CS:EIP来准确定位一个指令。

x86指令

mov指令与寻址方式

  • 寄存器寻址
movl %eax,%edx(%为寄存器标识,操作均为寄存器,与内存无关)

执行结果:edx = eax

  • 立即寻址
movl $0x123,%edx ($表示数值,表示将立即数存入寄存器中)

执行结果:edx = 0x123

  • 直接寻址
movl 0x123,%edx (将某个内存地址的内容存入寄存器中)

执行结果: edx = *(int32_t*)0x123

这里将0x123当作指针,寻找其指向的内存内容

  • 间接寻址
movl (%ebx), %edx (将寄存器中存放的值作为内存地址,取出其中内容,使用()表示**从地址取出内容**)

执行结果: edx = *(int32_t*)ebx

  • 变址寻址
movl 4(%ebx),%edx (将寄存器中存放的值作为基内存地址,加入偏移量后再取出相应内存地址对应内容)

执行结果: edx = *(int32_t*)(ebx+4)

b,w,l,q分别代表8位,16位,32位和64位

(样例中是movl,即表示是32位mov指令)

对于x86来说,大部分指令都能直接访问一个内存地址。

AT&T汇编格式与Intel汇编格式略有不同,Linux内核使用的是AT&T汇编

PUSH、POP、CALL和RET

pushl %eax

拆解指令:

subl $4,%esp
movl %eax,(%esp)

含义:将栈顶指针减4(栈从高到低增长),然后将eax里的值放入现在的栈顶所指向的内存中。

popl %eax

拆解指令:

movl (%esp),%eax
addl $4,%esp

含义:将栈顶值放入eax寄存器中,栈顶指针+4表示退栈

call 0x12345

拆解指令:

pushl %eip (当前的eip压栈,即要保存返回地址)
movl $0x12345,%eip (将 eip = 0x12345,即CPU要执行的下一条指令是0x12345指向的指令)

ret

拆解指令:

popl %eip (将call保存的eip还原到eip寄存器中)

约定

写汇编代码的时候不能直接修改eip寄存器,所以形如movl $8,%eip的用法是错误的!

C到汇编

enter:

pushl %ebp
movl %esp,%ebp

建立堆栈

leave:

movl %ebp,%esp
popl %ebp

退栈

实验截图

以下是我的实验截图,因为在学校学号是13061193,所以使用了这个数字作为个人的特殊标识:

函数调用堆栈分析

一些知识点

  • 函数的调用堆栈是由逻辑上的多个堆栈叠加起来形成的。
  • 函数的返回值默认使用eax寄存器存储返回给上一级函数,跟MIPS中的$v0寄存器的作用一样。

汇编代码分析

int g(int x)
{
return x + 3;
} int f(int x)
{
return g(x);
} int main(void)
{
return f(13061193) + 1;
}

首先看最简单的 int g(int x)函数,它不涉及到嵌套函数调用,只有一条语句用于返回 x+3

g函数编译成的汇编代码段即:

pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
addl $3,%eax
popl %ebp
ret

第1、2行汇编代码等价于enter,是一个存储函数基地址的过程。而在存储函数基地址之前,实际上还需要存储的是函数的参数与返回地址。返回地址的存入不是显式的,是在call语句时eip被存入栈中。

从开始到结束,整个过程可以用如下动图所示:

  • 左侧堆栈为执行完红色指令后的堆栈状态。
  • 使用main-eip、f-eip的意思是指,函数调用的返回点分别是在main、f函数中。
  • 使用main-ebp、f-ebp、g-ebp的意思是 这些分别是三个函数的基地址。
  • f-x 和 g-x 的意思是 这两个函数的参数 x 。

总结

冯诺依曼结构下的计算机是依靠CPU执行存储器中的代码段,配合存储器中的数据段等来工作的。

Linux内核分析课程笔记(一)的更多相关文章

  1. linux内核分析课程笔记(二)

    运行一个精简的操作系统内核 存储程序计算机是几乎所有计算机的基础逻辑框架. 堆栈是计算机中非常基础的东西,在最早计算机没有高级语言时,在高级语言出现之前,我们没有函数的概念.但高级语言出现后有了函数调 ...

  2. Linux内核分析课程总结

    Linux内核分析课程总结 By 20135203齐岳 知识梳理 (思维导图地址http://mindmap.4ye.me/mkxM0cFh/1) 从start _ kernel构造一个新的Linux ...

  3. Linux内核分析课程期中总结

    Linux内核分析课程期中总结 姓名:王朝宪 学号:20135114 注: 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com ...

  4. linux内核分析 课程总结

    Linux内核分析 链接汇总 Linux内核分析第一周学习总结--计算机是如何工作的 Linux内核分析第二周学习总结--操作系统是如何工作的 Linux内核分析第三周学习总结--构造一个简单的Lin ...

  5. 【课程总结】Linux内核分析课程总结

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 每周实验报告: 反汇编一个简单的C程序 ...

  6. Linux内核分析 读书笔记 (第一章、第二章)

    第一章 Linux内核简介 1.1 Unix的历史 Unix很简洁,仅仅提供几百个系统调用并且有一个非常明确的设计目的. 在Unix中,所有东西都被当做文件,这种抽象使对数据和对设备的操作是通过一套相 ...

  7. 20135239 益西拉姆 linux内核分析 读书笔记之第四章

    chapter 4 进程调度 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 多任务系统可以划分为两类: - 非抢占式多任务: - 进程会一直执行直到自己主动停止运行(这一 ...

  8. Linux内核分析 读书笔记 (第四章)

    第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间.进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有通过调度程序的合理调度,系统资源才能最大限 ...

  9. Linux内核分析 读书笔记 (第七章)

    第七章 链接 1.链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储器并执行. 2.链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于 ...

随机推荐

  1. [算法导论]二叉查找树的实现 @ Python

    <算法导论>第三版的BST(二叉查找树)的实现: class Tree: def __init__(self): self.root = None # Definition for a b ...

  2. Spark使用总结与分享

    背景 使用spark开发已有几个月.相比于python/hive,scala/spark学习门槛较高.尤其记得刚开时,举步维艰,进展十分缓慢.不过谢天谢地,这段苦涩(bi)的日子过去了.忆苦思甜,为了 ...

  3. C#人爱学不学9[C#5.0异步实例+WPF自己的MVVM Async应用 1/12]

    文章摘要: 1. 通过简单DEMO.让读者理解Task和Task<T>    学习过程中,掌握async和await 2. 理解同步和异步的执行 3. Task.Factory.Start ...

  4. 用户管理 之 在Linux系统中,批量添加用户的操作流程

    一.阅读此文件您需要掌握的基础知识: <Linux 用户(user)和用户组(group)管理概述><用户(user)和用户组(group)配置文件详解><Linux 用 ...

  5. MySQL解决插入emoji表情失败的问题

    普通的字符串或者表情都是占位3个字节,所以utf8足够用了,但是移动端的表情符号占位是4个字节,普通的utf8就不够用了,为了应对无线互联网的机遇和挑战.避免 emoji 表情符号带来的问题.涉及无线 ...

  6. Android之 -WebView实现离线缓存阅读

    前言 本篇博客要实现的是一个离线下载和离线阅读的功能,这是很多阅读类app都常见的一个功能,典型的应用就是网易新闻.什么是离线下载?其实这个概念是比较模糊,是离线之后下载呢,还是下载之后离线,但稍微有 ...

  7. C用函数指针模拟重载 C++重载

    C中为什么不支持重载,即同一作用域内不允许出现同名函数? 我们都知道重载是c++面向对象的特性.c语言中是不存在的.所谓重载简单来说就是一个函数名可以实现不同的功能,要么输入参数不同或者参数个数不同, ...

  8. 代码片段:基于 JDK 8 time包的时间工具类 TimeUtil

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “知识的工作者必须成为自己时间的首席执行官.” 前言 这次泥瓦匠带来的是一个好玩的基于 JDK ...

  9. db2安装及卸载

    创建用户和组: #创建组信息 groupadd -g db2iadm1 groupadd -g db2fadm1 groupadd -g dasadm1 #创建用户信息 useradd -u -g d ...

  10. IT项目经理成长手记

    1.流程化,项目化,工业化: 2.启动,规划,实施,监控,收尾.五个过程 3.需求管理,项目策划,项目监控,集成项目管理,定量项目管理,供应商协议管理,风险管理. 4.项目经理是熬出来的,伟大都是熬出 ...