程序的机器级表示(一)

这篇文章内容主要是了解汇编语言,以及它是怎么工作的。以下所介绍的内容均为在x86架构下,x64做了很多64位的扩展。重在理解实现方式及原理。:)

程序编码

  • 寄存器分类

    1. 程序计数器:用%eip表示,指示将要执行的下一条指令在存储器中的地址。
    2. 整数寄存器:用以存储地址或整数数据。
    3. 条件码寄存器:保存着最近执行的算数或逻辑指令的状态信息。
    4. 浮点寄存器:存放浮点数据。
  • 整数寄存器
    程序的机器级表示(一)_第1张图片

  • 机器级代码
    我们以一个例子来展示下机器代码如何解读:

    55 89 e5 8b 45 0c 03 45 08 01 05 18 a0 04 08 5d c3

    上述字节序列,反汇编之后展示如下:
    程序的机器级表示(一)_第2张图片
    Offset为机器码指令的地址,Bytes为指令值。
    注意观察第6行,01 05为add %eax指令,后面4个字节为18 a0 04 08,对应汇编地址0x804a018,因为是小端法字节排列。

访问信息

  • 操作数指示符
    操作数被分为三种类型:

    1. 立即数:即常数值,书写方式为’$’后跟一个整数。
    2. 寄存器:表示某个寄存器的内容。
    3. 存储器:根据计算出来的地址,访问某个存储器。

    程序的机器级表示(一)_第3张图片

  • 数据传送指令
    程序的机器级表示(一)_第4张图片
    MOV类中的指令,将源操作数复制到目的操作数中。源操作数指定的值是一个立即数,存储在寄存器中或存储器中。目的操作数指定一个位置,寄存器或者存储器地址。

    • MOVS和MOVZ指令类都是将一个较小的源数据复制到一个较大的数据位置,高位用符号扩展(MOVS)或者零扩展(MOVZ),示例如下:
      这里写图片描述

    • 通过push操作把数据压入栈中,通过pop操作删除数据。栈指针%esp保存着栈顶元素的地址。
      程序的机器级表示(一)_第5张图片

算数和逻辑操作

程序的机器级表示(一)_第6张图片

  • 加载有效地址
    leal指令是movl指令的变形,它的指令形式是从存储器读取到寄存器,但是实际上它并没有引用存储器,只是将其有效地址写入目的操作数。另外,它还可以用来描述算术操作,如:

    leal (%eax,%eax,2), %eax  //若%eax中值为x,则此表达式为x*3
    movl (%eax,%eax,2), %eax  //将存储器中地址为3x的值加载到%eax

    对比leal与movl,leal就是少了M[],不用再去存储器中找地址对应的值。

  • 一元操作和二元操作
    对于一元操作,只有一个操作数,既是源又是目的。这个操作数可以是寄存器或存储器位置。类似于(+ +)(- -)。
    对于二元操作,第二个操作数既是源又是目的。第一个操作数可以是立即数、寄存器或存储器位置,第二个操作数可以是寄存器或存储器位置。

  • 移位操作
    第一项k为移位量,第二项为需要操作的源及目的。移位量用单个字节编码,因为只允许0~31位的移位(针对X86)。移位量可以是立即数,或者放在单字节寄存器%cl中。

  • 特殊的算数操作
    程序的机器级表示(一)_第7张图片
    这里以乘法为例,两条乘法指令都要求一个参数必须在寄存器%eax中,而另外一个作为指令的源操作数给出,然后乘积存放在寄存器%edx(高32位)和%eax(低32位)中。mull为无符号乘法,imull为补码乘法。

你可能感兴趣的:(程序的机器级表示(一))