2018-2019-1 20175319 《信息安全系统设计基础》第三周学习总结
教材学习内容总结
汇编语言
- 汇编语言
- 汇编语言是直接面向处理器的程序设计语言
- 是机器指令的一种符号表示
- 由一条条指令构成
- 近距离观察机器代码
- 代码编译过程
- 入门级概念
- 两个抽象
- 指令集体系结构或指令集架构来定义机器级程序的格式和行为,它定义了处理器状态、指令的格式,以及每条指令对状态的影响。
- 机器级程序使用的内存地址,提供的内存模型看上去是一个非常大的字节数组
- X86-64指令
- 指令长度:1到15个字节不等
- 指令格式:OPER [DEST [,SRC]] ;注释
- 两个抽象
- 生成汇编文件
使用GCC编译器
gcc -Og -S code.c
- 反汇编
使用OBJDUMP
gcc -c code.c
objdump -d code.o
处理器
数据格式
访问信息
- X86-64中,中央处理单元(CPU)包含一组16个存储64位值的通用目的寄存器,用来存储整数数据和指针。
- 操作数指示符
- 立即数
- 寄存器
- 内存引用
- 数据传送指令
mov类指令:将源操作数的值复制到目的操作数中。
- 寻址方式
- 立即数寻址
操作数在指令中直接给出
注意:只能用于源操作数,数据长度应和目标操作数长度匹配 - 寄存器寻址
数存放在CPU的内部寄存器中
注意:源操作数和目的操作数的长度应该一致 - 存储器寻址
操作数存放在存储器中,指令中给出操作数的偏移地址信息
- 立即数寻址
算术和逻辑操作
- 加载有效地址指令leal实际上就是movl指令的变形。它的指令形式是从存储器读取数据到寄存器,但实际根本没引用存储器。
- 一元操作:只有一个操作数,既是源又是目的,可以是一个寄存器,或者存储器位置。
- INC 加1
- DEC 减1
- NEG 取负
- NOT 取补
- 二元操作:第一个操作数可以是立即数、寄存器或者储存器位置;第二个操作数既是源也是目的。可以是寄存器或者储存器位置,但是不能同时是储存器位置。
- ADD 加
- SUB 减
- IMUL 乘
- XOR 异或
- OR 或
- AND 与
- 移位操作:先给出移位量,第二项给出要移位的数值。
- SAL 左移
- SHL 左移(等同于SAL)
- SAR 算术右移
- SHR 逻辑右移
- 特殊算术操作
- 乘法
- 乘积截断
- imull双操作数
- 从两个32位操作数产生一个32位的乘积。
- 乘积不截断
- mull无符号数乘法
- imull有符号数乘法
- 要求一个参数必须在寄存器%eax中,另一个作为指令的源操作数给出。
- 乘积的高32位在%edx中,低32位在%eax中。
- 乘积截断
- 除法
- 有符号除法
- idivl 操作数
- 将DX:AX中的64位数作为被除数,操作数中为除数
- 结果:商在AX中,余数在DX中。
- 无符号除法
- divl指令
- 通常会事先设定寄存器%edx为0.
- 乘法
控制类指令
- 条件码
- CF: 进位标志。最近的操作使用最高位产生了进位。可以用来检查无符号操作数的溢出。
- ZF: 零标志。最近的操作得出的结果为0.
- SF: 符号标志。最近的操作得到的结果为负数。
- OF: 溢出标志。最近的操作导致一个补码溢出——正溢出或负溢出。 - 常用的访问方法有三种:
(1)可以根据条件码的某个组合,将一个字节设置为0或者1
(2)可以条件跳转到程序的某个其他的部分
(3)可以有条件地传送数据
- CF: 进位标志。最近的操作使用最高位产生了进位。可以用来检查无符号操作数的溢出。
- SET指令:执行比较指令,根据计算t=a-b的结果设置条件码
- 跳转指令
- 无条件跳转
- 直接跳转:跳转目标是作为指令的一部分编码的
- 间接跳转:跳转目标是从寄存器或存储器位置中读出的
- 比较和测试指令
- 访问条件码指令
- 跳转指令
- 循环指令
- do-while 循环
do body-statement while(test-expr);
- while 循环
while(test-expr) body-statement
- for 循环
for(init-expr; test-expr; update-expr) body-statement
过程
- 过程:一组指定的参数和一个可选的返回值实现某种功能。
- 形式:函数、方法、子例程、处理函数等。
- 实现过程需要的机器级支持机制
- 传递控制:将控制从函数P转移到函数Q
- 传递数据:把数据作为参数传递,从过程不返回或返回一个或多个值
- X86-64中,可以通过寄存器最多传递6个整型参数
- 分配和释放内存
- 栈上的局部存储
- 寄存器中的局部存储空间
- 传递控制:将控制从函数P转移到函数Q
- 栈帧
- 栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。
- 寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。
- 函数栈帧
支持过程调用和返回的指令:
数组及数据结构
- 数组
- 嵌套的数组:
int A[5][3]
- 定长数组:
#define N 16 typedef int fix_matrix[N][N]
- 变长数组
int A[expr1][expr2]
- 嵌套的数组:
- 结构体
用关键字struct声明,将多个对象集合到一个单位中 - 联合体
用关键字union声明,允许用几种不同的类型来引用一个对象 - 数组分配和访问
Xa代表的是起始地址,汇编代码使用move指令来简化访问:
movl (%edx,%ecx,4),%eax
异质的数据结构
- 结构
- 所有的组成部分在存储器中连续存放,指向结构的指针指向结构的第一个字节。
- 结构的各个字段的选取是在编译时处理,机器代码不包含字段的声明或字段名字的信息。
- 联合
- 一个联合的总大小等于它最大字段的大小
- 指向一个联合的指针,引用的是数据结构的起始位置。
- 结构和联合的应用
- 如果两个数据互斥,减少空间
- 访问不同数据的位模式
- 使用不同的位模式访问数据
- 用有符号数据存储,而返回的确实无符号的数据。
- C语言提供了两种结合不同类型的对象来创建数据类型的机制:
- 结构(structure),用关键字struct声明, 将多个对象集合到一个单位中。
- 联合(union), 用关键字union声明,允许用集中不同的类型来引用一个对象。
- 数据对齐
在计算机程序中将控制与数据结合
- 指针
- 指针用&符号创造、用*符号间接引用
- 指针从一个类型转为另外一个类型,只是伸缩因子变化,不改变它的值
- 指针可以指向函数
- GDB调试器
GDB支持对机器级程序的运行时评估和分析。
常用命令:
- 内存越界引用与缓冲区溢出
浮点代码
- XMM寄存器用来向函数传递浮点参数,以及从函数返回浮点值
- XMM寄存器%xmm0~%xmm7最多可以传递8个浮点参数。
- 函数使用寄存器%xmm0来返回浮点值
- 所有的XMM寄存器都是调用者保存的。被调用者可以不用保存就覆盖这些寄存器中任意一个
- GCC只用标量传送操作从内存传送数据到XMM寄存器或从XMM寄存器传送数据到内存。
代码学习内容
考试错题总结
- 1.下面的跳转指令与ZF有关的是()
A.jmp B.je C.js
D.ja E.jb F.jbe
正确答案: B D F
解析:
- 2.x86-64 Linux中,有关MOV,下面正确的是()
A .movw $0x50, %eax
B .movw %bp, %sp
C .movl ($1234), ($2345)
D .movb $10, (%rsp)
E .movq %rax, 4(%rbp)
F .movb (%rdi, %rcx), %ah
正确答案: B D E F
码云链接
https://gitee.com/J20175319/xinan_foundation/tree/master/week3
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 101/101 | 1/1 | 20/20 | |
第二周 | 49/150 | 1/2 | 18/38 | |
第三周 | 22/172 | 1/3 | 11/49 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:XX小时
-
实际学习时间:XX小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)