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


    实验四 第三章 程序的机器级表示

    本章学习内容是汇编语言,一定要能读懂

    3.1-3.7中练习重点:3.1,3.3,3.5,3.6,3.9,3.14,3.15,3.16,3.22,3.23,3.27,3.29,3.30,3.33,3.34

    X86 寻址方式经历三代:

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

    对于机器级编程来说,其中两种抽象尤为重要

         1  机器级程序的格式和行为,定义为指令集体系结构(ISA),它定义了处理器状态,指令的格式,以及每条指令对状态的影响
         2  机器级程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字节数组

    数据格式:由于是从16位体系结构扩展成32位,intel用术语字(word)表示16位数据类型,因此32位为双字(double words),64位数为4字(quad words)

    对于ISA,要有以下基本观念:IA32的ISA和x86-64的ISA,以及其他大多数ISA,在抽象时都将指令按顺序执行抽象。但是处理器的硬件可以并发地执行许多指令,并且采用了一些safeguards来确保并行执行之后的结果和一条一条顺序执行的结果一样

    一个IA32 CPU包含一组8个存储32位值的寄存器,用以存整数数据和指针:eax,ecx,edx,ebx,esi,edi,esp,ebp.大多数情况下前六个都用作通用寄存器,eax,ecx,edx的存储和恢复惯例不同于ebx,edi,esi(前三者为被调用者保存,后三者为调用者保存,详见3.7.3);最后两个用于存储指针,由于在过处理中非常重要,分别指向栈帧的顶部和底部,必须保持

    关于ISA的指令:

    一是,ISA中每条指令占用字节数不等,常用的指令所需的字节数少,不太常用的指令的字节数多,这样的话,相对于每条指令占用等长字节数的ISA,这种占用字节数不等的ISA为程序产生的总空间要更少。

     二是,ISA中的指令在设计时,达到了一个效果,对于一个二进制指令串,从某个字节开始,译码的结果是唯一的,这是达到了编码理论中“唯一可译性”的要求。

     (我觉得大概正是反汇编器正是利用了唯一可译性,从而将一串指令字节序列分割开来的)

     IA机器代码和原始的C代码差别很大

         1  程序计数器(PC)指令将要执行的下一条指令在存储器中的地址
         2  整数寄存器文件包含8个命名的位置,分别存储32位的值
         3  一些浮点寄存器存放浮点数据

    gcc -S xxx.c -o xxx.s 获得汇编代码,也可以用objdump -d xxx 反汇编

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

    二进制文件可以用od 命令查看,也可以用gdb的x命令查看。 有些输出内容过多,我们可以使用 more或less命令结合管道查看,也可以使用输出重定向来查看

                od code.o | more
                od code.o > code.txt
    

    当一个源文件生成了'.o'的目标二进制文件后,无法直接查看。

    但是还是有个查看目标代码文件内容的方法,就是对'.o'目标文件使用反汇编器。它的输出还是二进制文件,但是,反汇编器将这些二进制按照指令进行了分段。让我们知道哪一段是一个指令(格式上与汇编器产生的汇编文件一样,分行的)

     

    表中不同数据的汇编代码后缀

    C声明 Intel数据类型 汇编代码后缀 字节
    char 字节 b 1
    short w 2
    int 双字 l 4
    long int 双字 l 4
    long long int ----- - 4
    char * 双字 l 4
    float 单精度 s 4
    double 双精度 l 8
    long double 扩展精度 t 10/12

    数据传送指令有三个变种:movb(传送字节)movw(传送字)movl(传送双字)

    寄存器:

         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位的不会发生溢出
    

    操作数的三种类型:立即数、寄存器、存储器

         立即数:即常数值

         寄存器:表示某个寄存器内容

         存储器:根据计算出来的地址(通常称有效地址)访问某个存储器位置

         因此寻址方式也有多种,如:立即数寻址、寄存器寻址、绝对寻址、间接寻址、变址寻址、伸缩化  的变址寻址……

    有效地址的计算方式 Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s

    区分MOV,MOVS,MOVZ三个命令

         MOV相当于C语言的赋值”=“

         MOVS将作了符号扩展的字节传送到字

         MOVZ将作了零扩展的字节传送到字

    (不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下)

    mov族(mov指令还有很多兄弟指令如movb、movw、movsb、movzb)、pop、push

    movsb、movzb分别为符号扩展、零扩展,它们只拷贝一个字节,源操作数均为单字节,并设置目的操作数中其余的位,效果如下:

          初始假设:%dh=8D  %eax=98765432

          1   movb   %dh,%al       ;%eax=9876548D

          2   movsbl %dh,%eax    ;%eax=FFFFFF8D(目的操作数高24位设为源字节最高位,在这里为很显然为1,所以前24位为全F)

          3   movzbl %dh,%eax    ;%eax=0000008D(目的操作数高24位被设为0)

    pushl指令等价于:

              subl $4,%esp

              movl %ebp,(%esp)  //注意这里的括号引起的差别

    popl指令等价于:

               movl (%esp),%eax

               addl $4,%esp

    栈顶元素的地址是所有栈中元素地址中最低的

    1.指针其实是地址,间接引用指针就是将该指针放在一个寄存器中 ,然后在间接存储器引用中引用这个寄存器

    2.局部变量通常保存在寄存器中,而不是存储器(个人猜测应该是局部变量属于动态分配,局部变量因此被动态置入寄存器,而非存储器)

    例如调用exchange:

         int a = 4;

         int b = exchange(&a,3);

         printf("a=%d,b=%d ",a,b);

         打印出a=3,b=4

    (&(取址)创建一个指针,在本例中,该指针指向保存局部变量a的位置.然后函数exchange用3覆盖存储在a中的值,但是返回4作为函数的值)

    算术和逻辑操作

         移位操作 :sall==shll(填0)  sarl(算术右移,填符号位)  shrl(逻辑右移,填0)

         特殊算术操作:imull(有符号64位乘法)  mull(无符号64位乘法)  cltd(转换为四字) idivl(有符号除法)   divl(无符号除法)

    使用gcc –S –o main.s main.c -m32命令编译成汇编代码

  • 相关阅读:
    15分钟学会使用Git和远程代码库
    关注的一些个人博客记录
    vue实现筛选功能,文字选中变色
    为博客添加二次元人物方法
    收藏几个用的到的网站
    《代码整洁之道》学习记录
    《架构整洁之道》学习记录
    《指尖上行--移动前端开发进阶之路》学习记录
    《JavaScript设计模式》学习记录
    《以匠心,致设计》学习记录
  • 原文地址:https://www.cnblogs.com/20135305yg/p/4858854.html
Copyright © 2020-2023  润新知