20145316 《信息安全系统设计基础》第五周学习总结

20145316 《信息安全系统设计基础》第五周学习总结

教材学习内容总结

3.1历史发展

X86 寻址方式经历三代:

  • DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
  • 8086的分段模式
  • IA32的带保护模式的平坦模式

3.2程序编码

编译的优化

  • 命令行示例:gcc -O1 -o p p1.c p2.c

    -O1 表示使用第一级优化。优化的级别与编译时间和最终产生代码的形式都有关系,一般认为第二级优化-O2 是较好的选择。

    -o 表示将p1.c和p2.c编译后的可执行文件以及实现库函数的代码合并,产生的可执行文件最终命名为p。

两种抽象:

  • 指令集体系结构ISA

    是机器级程序的格式和行为,定义了处理器状态、指令的格式,以及每条指令对状态的影响。

    • 学到这里的时候认为ISA这个概念过于抽象,所以到网上查阅了相关知识,明白ISA就是“CPU里的硬性指令集”,而Intel和ARM处理器的本质区别就是,Intel使用复杂指令集(CISC),而竞争对手ARM则使用 精简指令集(RISC),这也就是ARM低功耗的原因。
      参考资料如下:

      CPU架构解析:ARM和x86大比拼

  • 机器级程序使用的存储器地址是虚拟地址

    看上去是一个非常大的字节数组,实际上是将多个硬件存储器和操作系统软件组合起来。

3.3数据格式

3.4访问信息

三种操作数:

  • 立即数:常数值。表示为$c标准表示的整数。
  • 寄存器:表示某个寄存器的内容。
  • 存储器:根据计算出来的地址访问某个存储器位置

数据传送指令

  • 栈的特点
    • 遵循“后进先出”的原则
    • push压栈,pop出栈
    • 栈顶:总是从这端插入和删除元素
    • 栈顶元素的地址是最低的
    • 栈指针%esp保存着栈顶元素的地址
  • 数据传送指令

数据传送示例

  • 局部变量通常保存在寄存器中;
  • 寄存器访问比存储器访问要快的多。

3.5算术和逻辑操作

四组操作

  • 加载有效地址:将有效地址写入目的操作数,目的操作数必须是寄存器。
  • 一元操作:只有一个操作数,可以是寄存器也可是存储器位置。
  • 二元操作:源操作数是第一个,可以是立即数、寄存器、存储器 ;目的操作数是第二个,可以是寄存器、存储器;两个不能同时为存储器。
  • 移位:第一个是移位量,用单个字节编码(只允许0-31位的移位),可以是立即数或者放在单字节寄存器%cl中 ;算术右移SAR,填上符号位;逻辑右移SHR,填上0。目的操作数可以是一个寄存器或存储器。

特殊的算术操作

3.6控制

条件码

  • CF:进位标志
  • ZF:零标志
  • SF:符号标志
  • OF:溢出标志

访问条件码

  • 条件码常用的使用方法

    • 根据条件码的某个组合,将一个字节设置为0或1。SET指令根据t=a-b的结果设置条件码;
    • 可以条件跳转到程序的某个其他部分;
    • 可以有条件的传送数据。

跳转指令及其编码

  • jump指令

    • 直接跳转:后面跟标号作为跳转目标
    • 间接跳转:*后面跟一个操作数指示符
  • 其他跳转指令

    除了jump指令外,其他跳转指令都是有条件的。有条件跳转是指根据条件码的某个组合,或者跳转或者继续执行下一条指令。

翻译条件分支

将条件表达式和语句从c语言翻译成机器语言,最常用的方式就是结合有条件和无条件跳转。

循环

  • 循环结构的三种形式

    • do-while:先执行循环体语句,再执行判断,循环体至少执行一次。
    • while: 把循环改成do-while的样子,然后用goto翻译
    • for: 把循环改成do-while的样子,然后用goto翻译

    汇编中用条件测试和跳转组合实现循环的效果。大多数汇编器根据do-while形式来产生循环代码,其他的循环会首先转换成do-while形式,然后再编译成机器代码。

条件传送指令

  • 实现条件转移的方式

    • 传统方式: 利用控制的条件转移。当条件满足时就,程序沿着一条执行路径进行,而当条件不满足时,就走另一路径。
      数据的条件转移方式。

    • 注意:基于条件数据传送的代码比基于条件控制转移的代码性能好。

switch语句

跳转表是一种非常有效的实现多重分支的方法,是一个数组,表项i是一个代码段的地址,这个代码段实现当开关索引值等于i时程序应该采取的动作。

3.7过程(重点)

栈帧结构

  • 机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复,以及本地存储。为单个过程分配的那部分栈称为栈帧。
  • 最顶端的栈帧以两个指针界定,寄存器%ebp为帧指针,寄存器%esp为栈指针。

转移控制

  • call指令

    • call指令有一个目标,即指明被调用过程起始的指令地址。
    • call指令的效果是将返回地址入栈。并跳转到被调用过程的起始处。
  • ret指令

    • ret指从栈中弹出地址,并跳转到这个位置。
    • ret指令返回到call指令后的那条指令。
  • leave指令

    • leave指令可以使栈做好返回的准备 等价于:

      movl %ebp,%esp

      popl %ebp

寄存器使用惯例

  • 程序寄存器组是唯一能被所有过程共享的资源。

    惯例是为了防止一个过程P调用另一个过程Q时寄存器中的值被覆盖

  • 使用惯例:

    • %eax,%edx,%ecx 调用者保存寄存器
    • %ebx,%esi,%edi 被调用者保存寄存器
    • %ebp,%esp 保持寄存器
  • 保存某值的两种方式

    • 由调用者保存。在调用之前就压进栈。
    • 由被调用者保存,在刚被调用的时候就压进栈,并在返回之前恢复。

3.11GDB的应用

代码调试中的问题和解决过程

  • 在为code.c进行优化编译的时候出现以下问题:

  • 后来仔细看了课本,发现应该是O1而不是01,这两个实在太容易看错了。而后,针对这样一个小小的马虎,我深入思考了一下O1的含义,1当然是优先级,那么O想必就是output输出的意思了,这样一记就不容易混淆了。

  • 下面是成功的截图:

反汇编

本周代码托管截图

其他(感悟、思考等,可选)

  • 这周的学习内容与大二下学期汇编语言的知识密切相关,实践比起第二章有所增加,但还是更侧重于理论,需要记忆的指令也很多。不同于背古诗,此类信息需要不断地在敲代码的实践中记忆,死记硬背可以应付每周的小测试,但于代码学习无益。同时,我们也要注重培养自己 速查的习惯,平时学习中遇到不会的指令和知识要赶快速查,要知道怎么查,在哪查,哪里找到的结果最可信,时间久了就发现每周开卷考试碰到不会的题,你做对的概率都会大很多。
  • 这个周课余时间利用“计蒜客”这一学习平台学习了一部分C++语言的知识。虽然信安专业的培养计划里并没有C++语言的学习,在很多方面C++也广为人诟病(批判者包括linux的创始人),但我认为:一,C++语言继承了c语言的绝大部分用法,却比C更高效,在学习C++的时候因为有C的基础,所以难度不会太大,在学习的同时也对C语言知识进行了复习;二,C++是面向对象的程序语言,与Java也很相似,通过学习C++也可以帮助自己更深入理解“面向对象”的含义,(学习Java的时候因为浮躁这些基础都是没有打牢的)。C++学习的这一部分的代码也已上传到git上。
  • 最近这两个周学习的最大收获是,不管学习什么科目的知识,快乐学习很重要,违背自己意愿的学习不可能收益太多。因为大一大二贪玩,基础比较差,很多时候看到课本那么多不认识的名词,永远调不通的代码,真的不想学了。之前的我总认为,学不进去就是懒惰,学不进去的时候就要给自己压力压制懒惰,道德捆绑自己学习。但通过不断地走弯路我摸索出了道理:学习效率低下学习热情不够高涨的时候,赶快收手,不要在自习室坐着浪费时间,敲几行代码就敲不下去了,赶快停下来,看电影,出去玩儿,做自己想做的事情。当自己内心对于玩乐的满足感已经过剩,未学习的罪恶感和ddl的压迫感扑面而来的时候,就会发现自己无比渴望学习,学习效率也会高很多。(当然,我不是鼓励大家拖延症,一天内的计划总是要在一天内做出来的)。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/2 15/30
第二周 56 /56 2/3 15/45
第三周 89/145 1/4 20/65
第五周 260/405 1/5 35/100

参考资料

原文地址:https://www.cnblogs.com/xxy745214935/p/5968234.html