Linux内核分析学习笔记

Posted Codcompiling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核分析学习笔记相关的知识,希望对你有一定的参考价值。

从今天开始学习网易云课堂孟宁老师的《Linux内核分析》课程,链接地址:http://mooc.study.163.com/course/USTC-1000029000#/info,记录课程学习笔记。

第一周的内容主要介绍了冯诺依曼体系结构ATT格式的32位x86汇编语言以及一个简单的c程序反汇编成汇编代码的执行分析过程

 

一、冯诺依曼体系结构——存储程序式计算机

  冯诺依曼体系结构的核心是存储程序,将数据和代码都存储在存储器中,都是二进制数据,通过特定的模块来分辨数据与代码。冯诺依曼体系结构的计算机包括运算器、控制器、存储器、输入单元、输出单元五大件。

技术分享

二、ATT格式的32位x86汇编

1、32位cpu的寄存器结构

通用寄存器

技术分享

8位寄存器:ah、al、bh、bl、ch、cl、dh、dl

16位寄存器:ax、bx、cx、dx、bp、si、di、sp

32位寄存器:eax、ebx、ecx、edx、ebp、edi、esi、esp

注意:

1、8位寄存器与16位寄存器是独立的,例如低8位寄存器al的运算结构溢出并不会影响到高8位寄存器ah,同样16位寄存器ax不会影响到32位寄存器eax的高16位

2、通常情况下eax作为累加器,ebx作为基址寄存器,ecx作为计数器,edx作为数据寄存器,ebp作为堆栈基指针寄存器(栈底),esi、edi作为变址寄存器,esp作为堆栈顶指针寄存器。

段寄存器

cs代码段寄存器

ds数据段寄存器

ss栈段寄存器

es扩展段寄存器

gs、fs附加段寄存器

标志寄存器

技术分享

2、几种ATT汇编指令

mov: 数据传送,可分为movb、movw、movl三种,分别传送一个字节、一个字、双字。

技术分享

pushl入栈,pushl %eax相当于:

                      subl $4, %esp

                      movl %eax, (%esp)

popl:出栈, popl %eax相当于:

                            

                      movl (%esp), %eax

                      add $4, %esp            

 

call:call f:相当于

                      pushl %eip

                      movl f, %eip

 

                      

ret: ret相当于:

                    popl %eip    

 

                      

enter:相当于:

                       pushl %ebp

                       movl %esp, %ebp

 

                           

leave:相当于:

                       movl %ebp, %esp

                       pop %ebp

 

注意:

Intel汇编与ATT汇编在多个操作数的时候,列出的操作数的顺序是相反的。

虽然上面对pushl和popl的解释中修改了eip,实际中程序员不能够手动直接操作eip,可以通过其他指令间接修改。

三、一个简单c程序反汇编分析

实验环境:https://www.shiyanlou.com/courses/running/555

1、试验阶段

 

编写c代码:

技术分享

编译生成汇编代码:

gcc –S –o main.s main.c –m32

 

观察分析汇编代码

删除无关信息后的汇编代码main.s:

技术分享

2、实验分析

函数调用堆栈的分析

观察上面汇编代码的每个函数main、f、g发现,每个函数的开始和结束都是一样的:

        pushl %ebp
        movl %esp, %ebp

        leave
        ret

上面两条指令相当于enter,用来构建一个函数堆栈框架,leave表示退出当前框架,分析如下:

进入函数前的初始状态:

技术分享

进入函数enter:

技术分享

中间进行一系列其他操作后,执行leave:

技术分享

最终又恢复到进入函数之前的状态

分析c程序的汇编代码

同c程序从main函数开始执行一样,汇编代码从main标签开始执行:

技术分享        技术分享

①从18行开始执行至22后:

技术分享此时取出22行代码call f, %eip = 23

②执行22行 call f,先将当前eip(23)入栈,然后将f的地址传入eip

pushl %eip
movl f, %eip

 

技术分享

③进入f,构造f的堆栈框架,执行至11行:

技术分享

执行

movl 8(%ebp), %eax
movl %eax,  (%esp)

 

技术分享

此时%eax = 8

④执行call g,进入g,构建g的堆栈框架:

技术分享

执行至6行:       %eax = 11

执行popl %ebp,销毁g堆栈框架:

技术分享

执行ret  即popl %eip后, %eip = 15

⑤继续执行15行leave,销毁f的堆栈框架:

pushl %ebp, %esp
popl %ebp

 

技术分享

执行16行ret:

技术分享

  此时 %eip = 23

  执行23行, %eax = 12

⑥执行24行,leave,销毁main的堆栈框架:

技术分享

 

又恢复到初始状态,而函数的返回值默认存放在%eax中,即%eax = 12,

后面ret,恢复至进入main之前的状态。

至此,上述c程序的汇编代码分析完毕。

 

以上是关于Linux内核分析学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核分析学习笔记

Linux内核分析——第七周学习笔记20135308

Linux内核分析——第一周学习笔记

《Linux内核分析》第六周学习笔记

《Linux内核分析》第七周学习笔记

Linux内核分析——第六周学习笔记