# 20145301 《信息安全系统设计基础》第5周学习总结
## 教材学习内容总结
* X86 寻址方式经历三代:
1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
2 8086的分段模式
3 IA32的带保护模式的平坦模式
* CPU包含一组8个存储32位值的寄存器
存整数数据和指针:eax,ecx,edx,ebx,esi,edi,esp,ebp。
大多数情况下前六个都用作通用寄存器,eax,ecx,edx的存储和恢复惯例不同于ebx,edi,esi(前三者为被调用者保存,后三者为调用者保存)。最后两个用于存储指针,由于在过处理中非常重要,分别指向栈帧的顶部和底部,必须保持。
* 编译:gcc -01 -o p p1.c,-01:表示使用第一级优化。通常提高优化级别会使最终程序运行得更快,但是编译时间可能会变长,用调试工具对代码进行调试会更困难。(实际中,第二级优化-02被认为是较好的选择)
* 两种抽象:
* 指令集结构ISA:是机器级程序的格式和行为,定义了处理器状态、指令的格式,以及每条指令对状态的影响。
* 机器级程序使用的存储器地址是虚拟地址,看上去是一个非常大的字节数组,实际上是将多个硬件存储器和操作系统软件组合起来。
* ATT与Intel:Intel省略了指示大小的后缀、寄存器前面的%、用不同的方式来描述存储器中的位置。
* 一些通常对C语言程序员隐藏的机器代码在IA32中是可见的:
* 程序计数器(在IA32中,通常称为“PC”,用%eip表示)指示将要执行的下一条指令在存储器中的地址。
* 整数寄存器:包含8个命名的位置,分别存储32位的数值,这些寄存器可以存储地址(对应C语言的指针)或整数数据,有的寄存器被用来记录某些重要的程序状态,其他的寄存器用来保存临时数据,例如过程的局部变量和函数的返回值。
* 条码寄存器:保存着最近执行的算术或逻辑指令的状态信息,他们用来实现控制或数据流中的条件变化。
* 浮点寄存器:一组浮点寄存器存放浮点数据
* 栈帧结构:机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复,以及本地存储。为单个过程分配的那部分栈称为栈帧。最顶端的栈帧以两个指针界定,寄存器%ebp为帧指针,寄存器%esp为栈指针。
* 汇编代码:
pushl %ebp 将寄存器%ebp的内容压入程序栈
movl %esp,%ebp 得到新栈低,将当前栈顶赋予栈低
popl %ebp过程调用结束,恢复旧栈低
ret 子程序的返回指令
* 二进制文件可以用od命令查看,也可以用gdb的x命令查看。有些输出内容过多,可以使用more或less命令结合管道查看,也可以使用输出重定向来查看。
od code.o | more
od code.o > code.txt
* gcc -S xxx.c -o xxx.s 获得汇编代码,也可以用objdump -d xxx 反汇编
* 64位机器上想要得到32代码:gcc -m32 -S xxx.c
* 二进制文件可以用od 命令查看,也可以用gdb的x命令查看。 有些输出内容过多
* 当一个源文件生成了‘.o‘的目标二进制文件后,无法直接查看。
* 数据传送指令有三个变种:movb(传送字节)movw(传送字)movl(传送双字)
* 寄存器:
esi edi可以用来操纵数组
esp ebp用来操纵栈帧
对于寄存器,特别是通用寄存器中的eax,ebx,ecx,edx,要理解32位的eax,16位的ax,8位的ah,al都是独立的
* 操作数的三种类型:立即数、寄存器、存储器
立即数:即常数值
寄存器:表示某个寄存器内容
存储器:根据计算出来的地址(通常称有效地址)访问某个存储器位置
* leal指令:从存储器读取数据到寄存器,是将有效地址写入到目的操作数(不改变任何条件码)
* CMP:与sub指令相似,但只设置条件码二不改变目的寄存器的值
* TEST:与AND指令相似,但只设置条件码二不改变目的寄存器的值
* jmp是无条件跳转,可以是直接,也可以是间接跳转;条件跳转只能是直接跳转
* 栈帧结构:机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复,以及本地存储
* 为单个过程分配的那部分栈称为栈帧,寄存器%ebp为帧指针,%esp为栈指针
* call指令:将返回地址入栈,并跳转到被调用过程的起始处,返回地址是在程序中紧跟在call后面的那条指令的地址
* ret指令从栈中弹出地址,并跳转到这个位置
寄存器%eax、%edx、%ecx被划分为调用者保存寄存器,寄存器%ebx、%esi、%edi被划分为被调用者保存寄存器
* call指令:call指令有一个目标,即指明被调用过程起始的指令地址; call指令的效果是将返回地址入栈。并跳转到被调用过程的起始处。
* ret指令:ret指从栈中弹出地址,并跳转到这个位置;ret指令返回到call指令后的那条指令。
* leave指令:leave指令可以使栈做好返回的准备,leave指令的使用在返回前,既重置了栈指针,也重置了帧指针
* 使用GDB的堆栈跟踪功能(GDB中有很多针对调用堆栈的命令,都需要一个目标栈帧,例如打印局部变量值的命令)
1.在栈帧之间切换
frame args 将当前栈帧设置为args(编号或Address)指定的栈帧,并打印该栈帧的简要信息。
up n 向上回退n个栈帧(更外层),n默认为1.
down n 向下前进n个栈帧(更内层),n默认为1.
2.打印栈帧信息(不移动栈帧)
frame 打印当前栈帧的简要信息。
info frame 打印当前栈帧的详细信息。
info frame args 打印指定栈帧的详细信息。
info args 打印函数参数信息。
info locals 打印当前可访问的局部变量的信息。
3.打印调用堆栈
backtrace 打印全部栈帧的简要信息,按Ctrl-c可终止打印。
backtrace n 打印最内层的n个栈帧的简要信息。
backtrace -n 打印最外层的n个栈帧的简要信息。
backtrace full 打印全部栈帧的详细信息。
backtrace full n 打印最内层的n个栈帧的详细信息。
backtrace full -n 打印最外层的n个栈帧的详细信息。
## 教材学习中的问题和解决过程
3.2 练习中关于改变push $0xff的指令后缀,请教同学后明白对于栈操作都是双字操作,所以不管是pop还是push都应该使用pushl和popl
## 课后作业中的问题和解决过程
## 本周代码托管截图
- [代码链接]([http://git.oschina.net/5301z/xxaqxt/tree/week5])
## 其他(感悟、思考等,可选)
这周的学习内容涉及许多汇编的知识,需要我们对汇编的相关知识进行再回顾与复习,加深巩固了对于汇编的理解。并且结合实验内容,从中体会到自己动手与眼高手低的区别,当时对汇编知识的一知半解,可能更多的原因在于并没有亲自动手去进行操作,希望通过这次的学习能够把汇编知识真正学好。
## 学习进度条
| | 代码行数(新增/累积)| 博客量(新增/累积)|学习时间(新增/累积)|重要成长|
| -------- | :----------------:|:----------------:|:---------------: |:-----:|
| 目标 | 4000行 | 24篇 | 400小时 | |
| 第一周 | 150/150 | 1/1 | 15/15 | 对Linux有了初步的认识
|第二周 | 200/350| 1/2|20/35|vim的使用 |
|第三周 |250/600|1/4|20/55|各种信息的表示方法
|第五周 |250/850|1/5|25/80|汇编与反汇编
## 参考资料
- [《深入理解计算机系统V2》学习指导]([http://www.cnblogs.com/rocedu/p/5826467.html])
- [Linux 基础入门(新版)]([https://www.shiyanlou.com/courses/1#])
- [《信息安全系统设计基础》 课程教学]([http://www.cnblogs.com/rocedu/p/5826175.html])
- [2016-2017-1 《信息安全系统设计基础》教学进程]([http://www.cnblogs.com/rocedu/p/5826112.html])