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


    第三章 程序的机器级表示

    X86 寻址方式经历三代:

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

    GCC将源代码转化为可执行代码的步骤:
    C预处理器——扩展源代码-生成.i文件
    编译器——产生两个源代码的汇编代码-——生成.s文件
    汇编器——将汇编代码转化成二进制目标代码——生成.o文件
    链接器——产生可执行代码文件

    ISA的定义:
    (1)指令集结构ISA
    是机器级程序的格式和行为,定义了处理器状态、指令的格式,以及每条指令对状态的影响。
    (2)机器级程序使用的存储器地址是虚拟地址
    看上去是一个非常大的字节数组,实际上是将多个硬件存储器和操作系统软件组合起来。

    机器级代码
    ISA:机器级程序的格式和行为,定义为指令集体系机构,它定义了处理器状态指令的格式,以及每条指令对状态的影响。
    机器级程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字符数组。
    PC:程序计数器。在IA32中,用%eip表示,指示将要执行的下一条指令在存储器中的地址。
    程序存储器:包含程序的可执行机器代码,操作系统需要的一些信息,用来管理过程调用和返回的运行时栈,以及用户分配的存储器块。
    代码示例
    64位机上想得到32位代码:gcc -m32 -S xxx.c
    编译并产生汇编目标文件xxx.o:gcc -O1 -c xxx.c
    获得汇编代码:gcc -S xxx.c -o xxx.s
    Ubuntu中获得汇编代码:gcc -S xxx.c更接近教材
    教材中获得汇编代码:gcc -O1 -S xxx.c(编译器使用的事第一级优化)
    汇编代码中需要牢记以下几句:
    pushl %ebp
    movl %esp,%ebp
    ……
    popl %ebp
    ret
    二进制文件可用od命令查看,也可以用gdb的x查看:(gdb)x/17xb sum表示检查17个十六进制的字节;
    显示代码过多或过少可用more、less结合管道查看,也可以用输出重定向:
    od xxx.o | more
    od xxx.o > xxx.txt
    反汇编:objdump -d xxx.o
    MAC OS中没有objdump,可用otool代替;
    汇编代码中另类结尾有'l'指的是大小指示符。

    注意: 64位机器上想要得到32代码:gcc -m32 -S xxx.c
    MAC OS中没有objdump, 有个基本等价的命令otool
    Ubuntu中 gcc -S code.c (不带-O1) 产生的代码更接近教材中代码(删除"."开头的语句)
    访问信息
    IA32的整数寄存器:

    其中,esi、edi可以用来操纵数组,esp、ebp用来操纵栈帧。
    通用寄存器中的eax,ebx,ecx,edx中,32位的eax,16位的ax,8位的ah,al都是独立的。例如:
    假定当前是32位x86机器,eax寄存器的值为0x8226,执行完addw (0x8266, %ax指令后eax的值是多少? 解析:0x8226+0x826=0x1044c, ax是16位寄存器,出现溢出,最高位的1会丢掉,剩下0x44c,不要以为eax是32位的不会发生溢出。 一、操作数指示符 操作数:指示出执行一个操作中要引用的源数据值,以及放置结果的目标位置。 1.操作数的三种类型 立即数 寄存器 存储器 2.结果存放的两种可能 寄存器中 存储器中 3.寻址方式 (1)立即数寻址方式 格式:)后加用标准c表示法表示的整数,如$0xAFF
    (2)寄存器寻址方式
    如%eax,与汇编中学过的AX寄存器类比。
    (3)存储器寻址方式
    直接寻址方式
    寄存器间接寻址方式
    寄存器相对寻址方式
    基址变址寻址方式
    相对基址变址寻址方式
    二、数据传送指令
    1.mov指令
    (1)功能
    把一个字节(字)操作数从源SRC传送至目的地DST
    (2)格式
    MOV DST,SRC
    (3)操作数
    MOV reg/mem, imm ;立即数寄存器或存储器
    MOV reg/mem/seg, reg ;寄存器的值寄存器/内存/段寄存器
    MOV reg/seg, mem ;内存单元的值寄存器/段寄存器
    MOV reg/mem, seg ;段寄存器的值寄存器/内存单元
    IA32的限制:两个操作数都不能指向存储器。
    (4)变种
    movb 传送字节
    movw 传送字
    movl 传送双字
    movs 符号位扩展
    movz 零扩展
    2.push&pop
    (1)堆栈
    需要注意两点:
    1.后进先出
    2.栈指针指向栈顶元素
    3.栈朝低地址方向增长
    (2)压栈push
    指令格式——PUSH r16/m16/seg
    指令功能
    第一步:SP←SP-2 ;堆栈指针SP上移
    第二步:(SS):(SP)←r16/m16/seg ;字操作数存入堆栈顶部
    注意 堆栈操作必须至少以字为单位,这时栈顶指针-2
    如果压入的是双字,栈顶指针-4
    (3)出栈pop
    指令格式——POP r16/m16/seg
    指令功能
    第一步:r16/m16/seg← (SS):(SP) ;栈顶的一个字传送到指定的目的操作数
    第二步:SP←SP+2 ;堆栈指针SP下移,指向新的栈顶
    栈顶指针变化同压栈。
    数据传送示例
    指针是地址。
    局部变量通常是保存在寄存器中,而不是存储器中。寄存器访问比存储器访问要快得多。

    算数和逻辑操作

    第一类:目的操作数必须是一个寄存器
    第二类:一元操作。操作数既是源又是目的。可以是寄存器也可以是存储器。
    第三类:二元操作。第二个操作数既是源又是目的。但两个操作数不能同时是存储器。
    第四类:移位操作。位移量是一个立即数或放在单字节寄存器%cl中。移位操作的目的操作数可以是一个寄存器或是一个存储器位置。
    更详细一点就是;
    SAL 算术左移
    SHL 逻辑左移
    SAR 算术右移(补符号位)
    SHR 逻辑右移(补0)
    源操作数:移位量——立即数或CL
    目的操作数:要移位的数值——寄存器或存储器
    特殊操作:
    1.乘法
    1)乘积截断
    imull
    双操作数,从两个32位操作数产生一个32位的乘积。
    (2)乘积不截断
    mull,无符号数乘法
    imull,有符号数乘法
    都要求一个参数必须在寄存器%eax中,另一个作为指令的源操作数给出。乘积的高32位在%edx中,低32位在%eax中。
    2.除法
    (1)有符号除法
    idivl 操作数
    将DX:AX中的64位数作为被除数,操作数中为除数,结果商在AX中,余数在DX中。
    (2)无符号除法
    divl指令
    通常会事先设定寄存器%edx为0.
    控制
    机器代码提供两种基本的低级机制来实现有条件的行为:测试数据值,然后根据测试的结果来改变控制流或者数据流。
    控制部分运用分支、循环语句实现。最核心的是跳转语句、有条件跳转、无条件跳转。
    条件码(状态寄存器):描述最近的算术或逻辑操作的属性。CF、ZF、SF、OF.
    leal指令不改变任何条件吗,因为是用来进行地址计算的。
    有两类指令只设置条件码而不改变任何其他寄存器。CMP指令根据他们的两个操作数之差来设置条件码。除了至设置条件码而不更新目标寄存器之外。CMP与SUB行为是一样的。
    CF:进位标志。检测无符号溢出。

    ZF:零标志。最近操作结果为0。

    SF:符号标志。最近操作结果为负数。

    OF:溢出标志。最近操作有补码溢出——正/负溢出。

    Leal进行地址运算所以不改变条件码。

    访问条件码

    条件码通常不会直接读取,常用三种方法:

    1.根据条件码的某个组合,将一个字节设置为0或者1
    2.条件跳转到程序的某个其他部分
    3.有条件的传送数据
    跳转指令及其编码

    跳转指令会导致执行切换到程序中一个全新的位置。
    在汇编代码中,这些跳转的目的地通常用一个标号指明。
    在产生目标代码文件时,汇编器会确定所有带标号指令的地址,并将跳转目标(目的指令的地址)编码为跳转指令的一部分。
    jmp指令是无条件跳转,他可以直接跳转也可以间接跳转。
    当执行PC有关寻址时,程序计数器的值是跳转指令后面的那条指令的地址,而不是跳转指令本身的地址。

    翻译条件分支
    有条件和无条件的跳转。
    Goto语句,无条件跳转。使代码难以阅读和调试。

    循环
    1.do-while
    2.while
    3.for
    条件传送代码
    实现条件操作的传统方式是利用控制的条件转移。
    数据的条件转移是一种替代策略。
    switch语句
    switch(开关)语句可以根据一个整数索引值进行多重分支。
    执行switch语句的关键步骤是通过跳转表来访问代码位置。

    过程
    一个过程调用包括将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分。

    栈帧结构

    机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复、本地存储。
    为单个过程分配的那部分栈成为栈帧。
    寄存器%ebp为帧指针
    寄存器%esp为栈指针
    栈帧结构

    机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复、本地存储。
    为单个过程分配的那部分栈成为栈帧。
    寄存器%ebp为帧指针
    寄存器%esp为栈指针
    转移控制
    Call指令有一个目标:指明被调用过程起始的指令地址。
    call指令效果:将返回地址入栈,并跳转到被调用过程的起始处
    寄存器使用惯例
    程序寄存器组是唯一能被所有过程共享的资源。
    必须保证当一个过程调用另一个过程时,被调用者不会覆盖某个调用者稍后会使用的寄存器的值。

    递归过程

    每个调用在栈中都有自己的私有空间,多个未完成调用的局部变量不会相互影响。
    当过程被调用时分配局部存储,当返回时释放内存。
    使代码继续到完成部分,回复栈和被调用者保存寄存器,然后返回的两种情况:终止条件,递归调用

  • 相关阅读:
    AJAX省市县三级联动
    AJAX,JSON搜索智能提示
    AJAX,JSON用户名校验
    原生JS操作AJAX
    JSON和GSON操作json数据
    Servlet之Cookie操作
    路径问题--转发、重定向、表单、超链接
    4418: [Shoi2013]扇形面积并|二分答案|树状数组
    近200篇机器学习&深度学习资料分享
    【Android】Eclipse自己主动编译NDK/JNI的三种方法
  • 原文地址:https://www.cnblogs.com/20135239-yxlm/p/4870128.html
Copyright © 2020-2023  润新知