x86的指令集可分为以下4种:

通用指令
x87 FPU指令,浮点数运算的指令
SIMD指令,就是SSE指令
系统指令,写OS内核时使用的特殊指令
下面介绍一些通用的指令。指令由标识命令种类的助记符和操作数(operand)组成。例如move指令:

指令操作数描述
movbI/R/M, R/M从一个内存位置复制1个字节(8位)大小的数据到另外一个内存位置
movwI/R/M, R/M从一个内存位置复制2个字节(16位)大小的数据到另外一个内存位置
movlI/R/M,R/M从一个内存位置复制1个字(32位,4字节)大小的数据到另外一个内存位置
movqI/R/M,R/M从一个内存位置复制1个双字(64位,8字节)大小的数据到另外一个内存位置

movl为助记符。助记符有后缀,表示作为操作数的对象的数据大小。b,w,l,q分别表示8位、16位、32位和64位的大小。
立即数(I)、寄存器(R)或内存地址(M),
在x86的汇编语言中,采用内存位置的操作数最多只能出现一个,例如不可能出现mov M,M指令。

通用寄存器中每个操作都可以有一个字符的后缀,表明操作数的大小,如下表所示。

C声明通用寄存器后缀大小(字节)
charb1
shortw2
(unsigned) int / long / char*l4
floats4
doublel5
long doublet10/12

如果在研究HotSpot VM虚拟机的汇编遇到了callq,pushq等指令时,后缀就是表示了操作数的大小。

汇编根据编译器的不同,有2种书写格式:
(1)Intel : Windows派系
(2)AT&T: Unix派系

下面我们以 AT&T 风格介绍一些常见指令:
注意AT&T汇编的第1个操作数在前,第2个操作数在后。 
mov指令:

movl %ecx,%eax
movl (%ecx),%eax
第一条指令将寄存器ecx中的值复制到eax寄存器;
第二条指令将ecx寄存器中的数据作为地址访问内存,并将内存上的数据加载到eax寄存器中。

cmov指令(支持带条件的mov指令):cmovxx
其中xx代表一个或者多个字母,这些字母表示将触发传送操作的条件。条件取决于 eflags寄存器的当前值。eflags寄存器如下图所示。

其中与cmove指令相关的eflags寄存器中的位有:
CF(数学表达式产生了进位或者借位)
OF(整数值无穷大或者过小)
PF(寄存器包含数学操作造成的错误数据)
SF(结果为正不是负)
ZF(结果为零)。

下表为无符号条件传送指令:

指令对描述eflags状态
cmova/cmovnbe大于/不小于或等于(CF或ZF)=0
cmovae/cmovnb大于或者等于/不小于CF=0
cmovnc无进位CF=0
cmovb/cmovnae大于/不小于或等于CF=1
cmovc进位CF=1
cmovbe/cmovna小于或者等于/不大于(CF或ZF)=1
cmove/cmovz等于/零ZF=1
cmovne/cmovnz不等于/不为零ZF=0
cmovp/cmovpe奇偶校验/偶校验PF=1
cmovnp/cmovpo非奇偶校验/奇校验PF=0

举个例子如下:
movl value,%ecx
cmp %ebx,%ecx
cmova %ecx,%ebx

第一条指令将vlaue数值加载到ecx寄存器中
第二条指令cmp指令比较ecx和ebx这两个寄存器中的值,用ecx减去ebx然后设置eflags
第三条指令 如果ecx的值大于ebx,使用cmova指令设置ebx的值为ecx中的值

lea指令:lea M,R
lea(Load Effective Address)指令将地址加载到寄存器。
lea计算源操作数的实际地址,并把结果保存到目标操作数,而目标操作数必须为通用寄存器

举例如下:

movl 4(%ebx),%eax
leal 4(%ebx),%eax  
第一条指令表示将ebx寄存器中存储的值加4后得到的结果作为内存地址进行访问,并将内存地址中存储的数据加载到eax寄存器中。

第二条指令表示将ebx寄存器中存储的值加4后得到的结果作为内存地址存放到eax寄存器中。

jmp指令:
jmp指令将程序无条件跳转到操作数指定的目的地址。jmp指令可以视作设置指令指针(eip寄存器)的指令。目的地址也可以是星号后跟寄存器的栈,这种方式为间接函数调用。例如:

jmp *%eax
将程序跳转至eax所含地址。

Jcc指令: Jcc 目的地址
其中cc指跳转条件,如果为真,则程序跳转到目的地址;否则执行下一条指令。相关的条件跳转指令如下表所示。
image.png

enter指令:
通过初始化ebp和esp寄存器来为函数建立函数参数和局部变量所需要的栈帧。相当于

push %rbp // 保存当前栈帧A的栈底
mov %rsp,%rbp // 把当前栈帧A的栈顶,作为新栈帧B的栈底

leave指令:
leave通过恢复ebp与esp寄存器来移除使用enter指令建立的栈帧。相当于

mov %rbp, %rsp // 把当前栈帧B的栈底,作为之前栈帧A的栈顶
pop %rbp// 弹出之前栈帧A的栈底

指令的格式如下:

int I
引起给定数字的中断。这通常用于系统调用以及其他内核界面。

参考:https://www.cnblogs.com/mazhi...


Martin
5 声望0 粉丝

后端


引用和评论

0 条评论