学习计时:共5小时 读书: 代码: 作业: 博客: |
一、学习目标 |
1. 理解逆向的概念以及
2. 掌握X86汇编基础,能够阅读(反)汇编代码
3. 了解ISA(指令集体系结构)
4. 理解函数调用栈帧的概念,并能用GDB进行调试
|
第三章 程序的机器级表示
3.1 历史观点
Inter处理器俗称x86
3.2 程序编码
gcc编译器编译流程:
·C预处理器扩展源代码;
·编译器产生两个源代码的汇编代码 p1.s p2.s
·汇编器将汇编代码转换成二进制目标代码文件 p1.o p2.o
·链接器将两个目标代码文件与实现库函数的代码合并,并产生可执行代码p
3.2.1 机器级代码
机器及编程的两个重要抽象
·集体系结构:机器级程序的格式和行为
·机器级程序使用的储存器地址是虚拟地址
一些通常对c语言程序员隐藏的处理器状态是可见的:
·程序计数器:要执行的下一条指令在存储器中的地址
·整数寄存器:存储地址或者整数数据
·条件码寄存器:保存最近执行的算术或逻辑指令的状态信息
·浮点寄存器:放浮点数据
程序存储器:
·程序的可执行机器代码
·操作系统需要的一些信息
·用来管理过程调用和返回的运行时栈
·用户分配的存储器块
3.2.3 关于格式的注释
·有'.'开头的行都是指导汇编器和连接器的命令
·左边有编号共引用,右边是注释
3.3 数据格式
·字:16位数据类型
·双字:32位数据类型
·四字:64位
大多数指令都是对字节或双字操作的
3.4 访问信息
·一个IA32中央处理单元(CPU)包含一组8个存储32位值得寄存器,这些寄存器用来存放整数数据和指针
3.4.1 操作数指示符
·操作数的三种
1.立即数:$+标准C表示的整数
2.寄存器
3.存储器
3.4.2 数据传送指令
·指令类:例如:MOV类由movb movw movl组成
·MOV类中的指令将源操作数的值复制到目的操作数中
·程序栈:后进先出原则 push1入栈 pop1出栈
3.5 算数和逻辑操作
·每个指令类都有对字节,字和双字数据进行操作的指令
·这些操作别分为四种:
1.加载有效地址
2.一元操作:一个操作数
3.二元操作:两个操作数
4.移位
3.5.1 加载有效地址
·加载有效地址指令leal实际上是movl指令的变形
·它的指令形式是从存储器读数据到寄存器,但实际上它根本没有引用存储器
3.5.2 一元操作和二元操作
·一元操作,只有一个操作数,既是源又是目的
·二元操作,第二个操作数既是源又是目的,源操作数是第一个,目的操作数是第二个
3.5.3 移位操作
·先给出移位量,第二项给出要移位的位数
3.5.5 特殊的算数操作
·imull:有符号全64位乘法
·mull:无符号全64位乘法
·cltd:转为四字
·idivl:有符号除法
·divl:无符号除法
3.6 控制
3.6.1 条件码
·CF:进位标志,可以用来检测无符号数的溢出
·ZF:零标志。最近的操作得出的结果为0
·SF:符号标志。最近的操作得到的结果为负数
·OF:溢出标志。最近操作导致一个补码(正/负)溢出
· leal指令不会改变任何条件码,因为它是用来进行地址计算的
·有两类指令只设置条件码而不改变任何其他条件码:
1.CMP:比较
cmpb cmpw cmpl
2.TEST:测试
testb testw testl
3.6.2 访问条件码
·条件码通常不会直接读取,常用的使用方法有三种:
1.可以根据条件码的某个组合,将一个字节设置为0或者1
2.可以条件跳转到程序的某个其他的部分
3.可以有条件的传送数据
·对第一种情况,我们将这一整类指令称为SET指令
3.6.3 跳转指令及其编码
·跳转指令会导致执行切换到程序中一个全新的位置
·在汇编代码中,这些跳转的目的地通常用一个标号指明
.
3.6.4 翻译条件分支
·讲条件表达式和语句从c语言翻译成机器代码,最常用的方式是结合有条件和无条件跳转
·gotodiff 使用了C语言中的goto语句
3.6.5 循环
·do-while
·while
·for
具体看书看习题
3.6.6 条件传送指令
·计算一个条件操作的两个结果,然后再根据条件是否满足从而选取一个
3.6.7 switch语句
·switch语句可以根据一个整数索引值进行多重分支(具体看书p145)
3.7 过程
·一个过程调用包括将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分
3.7.1 栈帧结构
·栈帧:为单个过程分配的那部分栈
·寄存器%ebp为帧指针
·寄存器%esp为栈指针 可移动
3.7.2 转移控制
·支持调用和返回的指令
3.7.3 寄存器使用管理
·程序寄存器组是唯一能被所有过程共享的资源
·根据惯例:
1.寄存器%eax %edx %ecx被划分为调用者保存寄存器
2.寄存器%ebx %esi %edi被划分为被调用者保存寄存器
3.8 数组分配和访问
3.8.1 基本原则
·对于数据类型T和整型常数N,声明如下:
T A[n];
它有两个效果。首先,他在存储器中分配一个L·N字节的连续区域;这里L是数据类型T的大小,用Xa来表示起始位置。其次,它引入了标识符A;可以用A作为指向数组开头的指针,这个指针的值就是Xa。可以用从0到N-1之间的整数索引来访问数组元素。数组元素i会被存放在地址为Xa+L*i的地方
3.8.2 指针运算
具体看书p159
·
3.8.3 嵌套的数组
具体看书p160
3.9 异质的数据结构
·C语言提供了两种结合不同类型的对象来创建数据类型的机制
结构,用关键字struck声明,将对各对象集合到一个单位中
联合,用关键字union声明,允许用几种不同的类型来引用一个对象
3.9.1 结构
·C语言的struct声明创建一个数据类型,将可能不同类型的对象聚合到一个对象中
(具体看书p164)
3.9.2 联合
·允许以多种类型来引用一个对象
(具体看书p167)
3.9.3 数据对其
·许多计算机系统对基本数据类型合法地址做出了一些限制,要求某种类型对象的地址必须是某个值K(通常是2,4或8)的倍数
p170
3.10 综合:理解指针
·每个指针都对应一个类型
·每个指针都有一个值
·指针用&运算符创建
·操作符用于指针的间接引用
·数组与指针紧密联系
·降至针从一种类型强制转换成另一种类型
·指针也可以指向函数
3.11 应用:使用GDB调试器
·常用的gdb命令:
后面的内容多为实例讲解,并不是很理解,应多看多理解。
3.15 总结:
本章,我们通过c语言方式,了解了机器级编程。机器级程序和它们的汇编代码表示,与c语言的差别很大。在汇编语言程序中,各种数据类型之间的差别很小。程序是以指令序列来表示的,每条指令都完成一个单独的操作。部分程序状态,如寄存器和运行时栈,对程序员来说是直接可见的。