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

教材学习内容总结

历史观点

  • X86 寻址方式经历三代:

      1、 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
      2、 8086的分段模式
      3、 IA32的带保护模式的平坦模式
    
  • linux使用了平坦寻址方式

程序编码

  • ISA(指令集体系结构)定义了处理器状态指令的格式,以及每条指令对状态的影响

  • PC(程序计数器)指示将要执行的下一条指令在存储器中的地址

  • gcc -S xxx.c -o xxx.s 获得汇编代码,用objdump -d xxx.o 反汇编,函数前两行汇编代码pushl %ebp,movl %esp,%ebp和后两行代码popl %ebp,ret所有函数都有,建立函数调用帧

  • Ubuntu中 gcc -S code.c (不带-O1) 产生的代码更接近教材中代码

  • 二进制文件可以用od 命令查看,也可以用gdb的x命令查看

  • gcc -S 产生的汇编中可以把 以“.”开始的语句都删除了再阅读

数据格式

  • 不同数据的汇编代码后缀

访问信息

  • 寄存器中 esi edi可以用来操纵数组,esp ebp用来操纵栈帧
  • 对于寄存器,特别是通用寄存器中的eax,ebx,ecx,edx, 32位的eax,16位的ax,8位的ah,al都是独立的
  • 操作数的三种类型:立即数、寄存器、存储器
  • 有效地址的计算方式 Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s
  • MOV相当于C语言的赋值”=“,注意ATT格式中的方向, 另外注意不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下
  • 栈帧与push pop; 注意栈顶元素的地址是所有栈中元素地址中最低的
  • 指针就是地址;局部变量保存在寄存器中

算术和逻辑操作

  • 注意移位操作移位量可以是立即数或%cl中的数

控制

  • 有条件跳转的条件看状态寄存器
  • leal指令不改变任何条件码,因为是用来进行地址计算的
  • CMP指令根据他们的两个操作数之差来设置条件码。除了只设置条件码而不更新目标寄存器之外,CMP与SUB行为是一样的
  • SET指令根据t=a-b的结果设置条件码
  • 跳转指令会导致执行切换到程序中一个全新的位置。这些跳转的目的地通常用一个标号指明
  • 跳转语句主要有有条件跳转(if,switch,while,for)和无条件跳转jmp(实现goto)

过程

  • IA32通过栈来实现过程调用
  • call指令的效果是将返回地址入栈,并跳转到被调用过程的起始处。返回地址是在程序中紧跟在call后面的那条指令的地址
  • ret指令从栈中弹出地址,并跳转到这个位置。栈指针要指向前面call指令存储返回地址的位置
  • 函数返回值存在%eax中

教材学习中的问题和解决过程

P108学习反汇编指令时在完全按照书上的步骤操作的情况下出现无法找到code.o文件的情况

  • 解决:既然提示无此文件,我就按照GCC编译的格式产生code.o文件,于是可以顺利进行反汇编

  • 虽然最后用最原始的方法解决,但是书上的确说会产生.o文件,但是返回文件夹查看后发现我产生的是一个名字为1的文件,发现有可能是gcc的指令中o的大小写出现问题,于是用了一个test.c测试

  • 这一次用gcc -O1 -c 发现可以产生test.o文件,用小写的o后面的1会被认为是输出的对象文件名,所以一开始才会只产生了1文件

作业完成过程

作业C语言代码如下

使用gcc –S –o main.s main.c -m32编译

删除gcc产生代码中以"."开头的编译器指令

分析如下

  • main:开始执行,保存%ebp,并设置新的帧指针

       pushl   %ebp
       movl    %esp,%ebp
    
  • pushl $8分配4字节的栈空间,并且设置arg1=8,相当于

      subl	$4,%esp
      movl	$8,(%esp)
    
  • call调用b:

  • b同样初始化帧指针,分配栈空间

      pushl   %ebp
      movl    %esp,%ebp
    
  • pushl 8(%ebp)将%esp中的8存入栈中,相当于

      subl	$4,%esp
      movl	8(%ebp),%eax
    
  • call调用a:

  • a被调用,初始化栈指针,分配栈空间

  • 将 %eax 与立即数 1 相加

      addl	$1,%eax
    
  • 在a结束前弹栈

      popl    %ebp
    
  • ret返回b中call的调用位置

  • b也结束,return返回main中call调用的位置

  • main继续 %eax 加14的操作

      addl    $14,%eax
    
  • leave为返回准备栈,相当于%ebp出栈,最后ret结束

  • 图示如下

家庭作业

3.56

  • 补充后的C代码如下

  • 本来想通过补充后的C代码进行汇编,来验证代码的准确性

  • 后来发现自己编写后汇编的代码与题目中的原代码相差甚远,后来想到可能是不同的编译器转换规则可能不同的原因导致。

代码托管情况

代码托管链接(http://git.oschina.net/20145214/znn20145214/tree/master/Week04)

代码行数统计

代码托管截图

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

  • 本周主要是汇编的学习,由于之前对汇编的学习不系统,理解得也不够透彻,所以本周的学习还是相对有一些吃力,虽然3.1到3.6的内容大部分都相当于在复习,但是做题的时候,看到一些指令还是要返回到前面翻书查看指令的具体用法
  • 在教材学习的过程中,深刻地体会到了大小写的致命性,由于对大小写的忽略导致学习的进度一度停滞不前,说明以后看书的时候还是需要多多注意细节的差异,毕竟细节才是决定成败的关键嘛

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第零周 0/0 1/1 5/5 使用虚拟机安装linux系统,安装ubuntu
第一周 100/100 1/2 20/25 掌握核心的linux命令,了解了linux操作系统
第二周 76/176 1/3 30/55 学会了虚拟机上的C编程
第三周 214/390 1/4 20/75 初步学习计算机中各种数的表示和运算
第五周 138/528 1/5 25/100 通过学习汇编,了解逆向的思想应用

参考资料

Copyright © 2024 20145214张宁
Powered by .NET 9.0 on Kubernetes