• 20135337—信息安全系统设计基础第四周学习总结


    第3章 程序的机器级表示

    一、知识点

    3.1 X86寻址方式经历的三代

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

    3.2 程序编码

    1、ISA 指令集体系结构

    定义了处理器状态、指令的格式,以及每条指令对状态的影响

    2、

    处理器状态
    • PC 程序计数器(%eip):指示将要执行的下一条指令在存储器中的位置。
    • 整数寄存器文件:包含8个命名的位置,分别存储32位的值。它们可以存储地址、证书数据,记录程序状态、保存临时数据。
    • 条件码寄存器:保存最近执行的算术或逻辑指令的状态信息。
    • 浮点寄存器:存放浮点数据
    代码
    获得汇编代码:gcc -S xxx.c -o xxx.s
    反汇编:objdump -d xxx
    *在MAC OS中没有objdump指令,用等价功能的otool
    *64位机器上想要得到32代码:gcc -m32 -S xxx.c
    
    二进制文件可以用od 命令查看,也可以用gdb的x命令查看。有些输出内容过多,我们可以使用 more或less命令结合管道查看,也可以使用输出重定向来查看:
    od code.o | more
    od code.o > code.txt
    

    3.3 数据格式

    b-字节
    w-字
    l-双字(注意:与之后出现的less(少、小、低)区别,此处是long)
    

    3.4 访问信息

    1、寄存器

    1.数据寄存器
    32位通用寄存器eax、ebx、ecx和edx。
    *对低16位数据的存取,不会影响高16位的数据。
    *可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器
    低16位寄存器分别命名为:ax、bx、cx和dx。
    *不能作为基址和变址寄存器来存放存储单元的地址。
    
    2.变址寄存器
    32位通用寄存器esi、edi,低16位对应先前CPU中的si和di。
    *用于存放存储单元在段内的偏移量,也可存储算术逻辑运算的操作数和运算结果。
    
    3.指针寄存器
    32位通用寄存器ebp和esp,低16位对应先前CPU中的sbp和sp。
    *用于存放堆栈内存储单元的偏移量,也可存储算术逻辑运算的操作数和运算结果。
    
    4.指令指针寄存器
    eip、ip
    *存放下次将要执行的指令在代码段的偏移量。
    
    8位寄存器有: AH、AL、BH、BL、CH、CL、DH和DL等;
    16位寄存器有:AX、BX、CX、DX、SI、DI、SP、BP和段寄存器等;
    32位寄存器有:EAX、EBX、ECX、EDX、ESI、EDI、ESP和EBP等。
    内存中的变量存储的是其偏移地址
    

    2、寻址方式

    操作数:立即数($9)、寄存器(%eax)、存储器
    有效地址=立即数+基址寄存器的值+变址寄存器的值*比例因子
    
    
    区别各种寻址方式时,注意各自的特点。(参考:http://www.cnblogs.com/satng/archive/2010/01/15/2138180.html)
      只有一个常量,是立即(数)寻址方式;
      只有一个寄存器名,是寄存器寻址方式;
      其他则是存储器寻址方式。
      *
      用中括号括起一个常量是直接寻址方式;
      用中括号括起一个寄存器名,是寄存器间接寻址方式;
      用中括号括起一个寄存器名和一个常量是寄存器相对寻址方式;
      用中括号括起两个寄存器名是基址变址寻址方式;
      用中括号括起两个寄存器名和一个常量是相对基址变址寻址方式。
    

    3、指令

    1.数据传送指令
    MOV 传送字或字节.
    MOVS 先符号扩展,再传送.
    MOVZ 先零扩展,再传送.
    *源操作数:立即数,存储在寄存器中或者在存储器中
     目的操作数:寄存器、存储器地址。
    
    PUSH 把字压入堆栈.
    POP 把字弹出堆栈.
    *栈顶-此端插入和删除元素。
     栈顶元素的地址是所有栈中元素地址中最低的。
     栈指针%esp保存着栈顶元素的地址。
    *压栈——指针先减,数据再入
     弹栈——数据先出,指针再加
    
    2.目的地址传送指令
    leal 加载有效地址。
    从存储器读数据到寄存器,将有效地址写入目的操作数。
    目的操作数必须是一个寄存器。
    
    3.算术、逻辑运算指令

    一元操作:操作数可以是:寄存器、存储器位置

    INC 加 1.
    DEC 减 1.
    NEG 取负
    NOT 取补
    

    二元操作:第一个操作数可以是:立即数、寄存器、存储器位置。第二个数可以是:寄存器、存储器位置。(不能同时是存储器位置)

    ADD 加法.
    SUB 减法.
    IMUL 整数乘法.
    IDIV 整数除法.
    
    AND 与运算.
    or 或运算.
    XOR 异或运算.
    

    移位操作:移位量:立即数,或者放在单字节寄存器元素%cl中。目的操作数可以是:寄存器、存储器位置

    SHL 逻辑左移.
    SAL 算术左移.(=SHL)
    SHR 逻辑右移.(高位补0)
    SAR 算术右移.(高位补符号)
    

    比较和测试:仅修改标志位,不回送结果

    CMP 比较.(两操作数作减法).
    TEST 测试.(两操作数作与运算).
    

    条件码寄存器

    CF:进位标志
    ZF:零标志
    SF:符号标志
    OF:溢出标志
    
    CMP 比较.(两操作数作减法,右操作数减左操作数).
    TEST 测试.(两操作数作与运算).
    * 比较和测试仅修改标志位,不回送结果
    
    条件码寄存器不能直接读取,有三种方法:
    	set指令:根据条件码,设置一个字节。
    	jump指令:根据条件码进行跳转,即控制的条件转移。
    	cmov条件传送指令:根据条件码决定是否进行mov操作
    *这些指令判断条件是否满足,是根据条件码的组合决定的。
    *sete (e:equal)  setl (l:less与之前的long进行区别)
    

    4、语句

    *与C语言中的语句功能相同
    if-else
    do-while
    while
    for
    switch(&—创建一个指向数据值的指针;&&—创建一个指向代码位置的指针;jmp中前缀*—间接跳转)
    

    5、过程

    1、栈、栈帧
    栈帧——为每一个过程分配的内存空间,它包含两个特殊的参数,栈指针和帧指针。一个指向栈顶一个指向栈低。
    栈是向低地址增长的,也就是说,栈的底部在内存的高地址部分。
    
    帧指针:%ebp,指向栈底。
    栈指针:%esp,指向栈顶,栈指针可以移动,来分配或释放空间。
    	%esp减小——分配空间
    	%esp增大——释放空间
    
    2、IA32提供的转移控制指令
    以下三个指令缺一不可!!!否则,调用过程就不完整啦!!!
    call指令的具体 效果,是将返回地址压入调用者的栈中,作为它的栈里面的最后一个元素,并且将程序计数器eip里面的数值改变为被调用者的地址。
    
    ret指令是从栈中弹出这个返回地址,让程序回到调用之前被调用函数下一条指令继续进行。
    
    leave指令一般在ret指令之前进行,它是为回到返回地址进行一些准备工作,比如回收栈空间,并且重置栈指针和帧指针,因为你调用完成之后是需要把两个重要的指针复位的。
    *leave的指令 等价于这两条指令 movl ebp esp , popl ebp。第一条指令的作用就是回收栈空间,把栈顶指针向上移动,和ebp指向同一条指令,ebp现在所指向的内存空间存储的是调用者的 ebp,也就是旧的ebp的值。第二条指令,将旧的ebp值恢复到ebp的寄存器,也就是将帧指针 重新指向调用者的栈底,此时esp因为弹出一个元素的原因 ,向上移动栈指针,正好指向了返回地址的那一块内存空间,此时就可以利用ret命令进行返回了。
    
    3.过程

    #######1.寄存器使用
    调用者——%eax、%edx、%ecx
    被调用者——%ebx%esi%edi
    #######2.具体过程
    需要明确,向被调用者传递的参数是存储在调用者的栈中的。

    调用者栈的结束边界是在执行call指令的时候将返回地址压入栈中,被调用者栈的起始边界是在保存祯指针%ebp的值之后。
    
    被调用者的栈的起始点都是调用者%ebp的值,为了以后恢复方便。过程调用期间,会通过栈来分配一些自由的内存空间用于存储一些临时的变量,但是在这种类型的分配方式下,是要遵循分配的空间 必须是16字节整数倍这样的 一个规定 ,这是X86编程的一个规定。所以你就会看到,在很多时候,明明分配了很多空间,但是都没用到。
    被调用过程在进行的时候,要先将旧的%ebp压入栈中,并且初始化两个栈指针,之后要将一些被调用者保存的寄存器里面的值压入栈中保存,防止在之后的代码中会覆盖这些数据。
    

    6、GDB中bt、frame、up、down的使用(都会打印出移动到的栈层的信息)

    bt n
    n是一个正整数,表示只打印栈顶上n层的栈信息。
    bt -n
    -n表一个负整数,表示只打印栈底下n层的栈信息。

    frame n
    n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

    up n
    表示向栈的上面移动n层,可以不打n,表示向上移动一层。

    down n
    表示向栈的下面移动n层,可以不打n,表示向下移动一层。

    查看当前栈层的信息,你可以用以下GDB命令:
    frame 或 f(会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。)

    7、实验楼实践

    (更换了函数中的数字为学号。)
    






    汇编:gcc -S five.c
    反汇编:objdump -d five.o

    思考:把以“.”开头的行的指导汇编器和链接器的命令的开头“.”删去,就是汇编代码了。


    该问题已在小组中提问。

    二、遇到的问题及解决

    1.练习题中出现cmovl和cmovge(参考:http://blog.sina.com.cn/s/blog_5438b6c30100kvvp.html)
    解决:CMOVL/CMOVNGE——小于/不大于或者等于——(SF异域OF) = 1
    
    2.练习题29中出现jmp .L7(,%eax,4),不理解括号前已经用标识了此处需要跳转,为什么又要写出括号中的地址?(已在答疑论坛中提问)
    我理解的是:L7是跳转表,*指示此处跳到跳转表,括号中的地址是具体跳转到的位置。
    
    3.寻址方式这部分比较绕,不容易理清。
    解决:归纳总结。参考http://www.cnblogs.com/satng/
    
    4.阅读书149页的图3-21时,加上书上描述栈、帧指针变化过程,有些绕不清栈和栈帧的关系了。
    栈:
    栈底指针和栈顶指针(执行时,它在动),栈底位于最下。
    一种特殊的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。
    存储原则是先进后出。
    对栈的插入与删除操作中,不需要改变栈底指针。
    栈是从高地址向低地址延伸的。
    

    栈——相对整个系统而言,调用栈相对某个进程而言。

    栈帧——则是相对某个函数而言,调用栈就是正在使用的栈空间,由多个嵌套调用函数所使用的栈帧组成。

    栈帧表示程序的函数调用记录,而栈帧又是记录在栈上面。(为单个过程分配的那部分栈称为栈帧)
    每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。因此栈作用就是用来保持栈帧的活动记录(即函数调用)。
    *
    参考:http://blog.csdn.net/ylyuanlu/article/details/18947951
    http://blog.chinaunix.net/uid-16459552-id-3257539.html
    
    5.过程这部分问题,自己不能很好的归纳总结,理清思路。
    调用者caller,被调用者callee。
    当caller调用callee时,caller的返回地址被压入栈中,形成caller栈帧的末尾。
    返回地址:就是当程序从callee返回时应该继续执行的地方(指令的地址),当被调用过程返回时,程序会从此处继续执行。
    callee的栈帧从保存的帧指针的值(%ebp)开始,其后即为其保存的寄存器的值,和callee调用其他过程的参数。
    
    参考:http://blog.csdn.net/livelylittlefish/article/details/5051545
    http://m.blog.csdn.net/blog/u010092734/38379391,阅读完之后,发现别人总结的非常清晰。(一些内容在上面的知识点总结体现了)
    
    6.实验楼中出现的


    解决:汇编:gcc -S five.c
    反汇编:objdump -d five.o

    三、其他

    做语句这部分的练习题时,只能做到一句句的顺序的读出汇编代码,但是不能准确的对应到C语言代码,只能对比课后答案。希望老师上可以带着练习练习。
  • 相关阅读:
    [转]中英文停止词表(stopword)
    [转]Memcached常用命令及使用说明
    Java导出excel并下载功能
    Java List 汉字进行排序
    Tengine笔记3:Nginx的反向代理和健康状态检查
    Tengine笔记2:通过IP、域名、端口实现虚拟主机
    Tengine笔记1:安装Tengine和Tengine说明
    Linux学习笔记6-Linux根目录下各个目录的作用
    Linux学习笔记5-搭建内网Yum源
    Python学习笔记10-Python MysqlHelper ,MySql 辅助类
  • 原文地址:https://www.cnblogs.com/zzzz5/p/4868610.html
Copyright © 2020-2023  润新知