x86-64常用指令总结


个人博客

本文将《深入理解计算机系统》中涉及到的 x86-64 常用指令进行了总结,需要的时候方便查询

本文采取的是ATT格式的汇编代码,这是 gcc、objdump 等工具的默认格式。但是在其他一些工具里,比如说微软的工具和 Intel 的文档里,其汇编代码都是 Intel 格式的

数据格式

Intel 数据类型汇编代码后缀大小(字节)
字节b1
w2
双字l4
四字q8
单精度s4
双精度l8
  1. Intel 使用 字(word) 表示16位数据类型

  2. 汇编指令除了要指明操作对象,还要指明操作对象的数据类型及长度。为了指明操作对象的数据类型及长度,可以在指令后面加上表示数据类型的后缀,比如 movlmovq分别表示操作的对象为双字和四字,gcc 生成的汇编代码一般都有这样的一个字符后缀;但其实操作对象的长度也可以通过寄存器给出,比如说eax和rax分别表示32位和64位,因此指令后面不加后缀也是可以的

寄存器

在这里插入图片描述

%ebp%esp:栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,%esp总是指向当前栈帧的顶部(低地址),而%ebp通常指向当前栈帧的底部(高地址),用于在栈帧中寻址

操作数格式(寻址方式)

类型格式操作数值名称
立即数$ImmImm立即数寻址
寄存器 r a r_a raR[ r a r_a ra]寄存器寻址
存储器ImmM[Imm]绝对寻址
存储器( r a r_a ra)M[R[ r a r_a ra]]间接寻址
存储器Imm( r b r_b rb)M[Imm+R[ r b r_b rb]](基址+偏移量)寻址
存储器( r b , r i r_b,r_i rb,ri)M[R[ r b r_b rb]+R[ r i r_i ri]]变址寻址
存储器Imm( r b , r i r_b,r_i rb,ri)M[Imm+R[ r b r_b rb]+R[ r i r_i ri]]变址寻址
存储器( , r i , s ,r_i,s ,ri,s)M[R[ r i r_i ri] ⋅ s \cdot s s]比例变址寻址
存储器Imm( , r i , s ,r_i,s ,ri,s)M[Imm+R[ r i r_i ri] ⋅ s \cdot s s]比例变址寻址
存储器( r b , r i , s r_b,r_i,s rb,ri,s)M[R[ r b r_b rb]+R[ r i r_i ri] ⋅ s \cdot s s]比例变址寻址
存储器Imm( r b , r i , s r_b,r_i,s rb,ri,s)M[Imm+R[ r b r_b rb]+R[ r i r_i ri] ⋅ s \cdot s s]比例变址寻址

数据传送指令

指令效果描述
MOV  S , D \text{MOV }S, D MOV S,D D ← S D\leftarrow S DS传送
movb
movw
movl
movq
movabsp
传送字节
传送字
传送双字
传送四字
传送绝对的四字

x86-64 约定,传送指令的两个操作数不能都指向内存位置

指令效果描述
MOVZ  S , D \text{MOVZ }S, D MOVZ S,D D ← 零扩展 ( S ) D\leftarrow \text{零扩展}(S) D零扩展(S)以零扩展进行传送
movzbw
movzbl
movzwl
movzbq
movzwq
将做了零扩展的字节传送到字
将做了零扩展的字节传送到双字
将做了零扩展的字传送到双字
将做了零扩展的字节传送到四字
将做了零扩展的字传送到四字
指令效果描述
MOVS  S , D \text{MOVS }S, D MOVS S,D D ← 符号扩展 ( S ) D\leftarrow \text{符号扩展}(S) D符号扩展(S)以零扩展进行传送
movsbw
movsbl
movswl
movsbq
movswq
movslq
cltq






%rax ← \leftarrow 符号拓展(%eax)
将做了符号扩展的字节传送到字
将做了符号扩展的字节传送到双字
将做了符号扩展的字传送到双字
将做了符号扩展的字节传送到四字
将做了符号扩展的字传送到四字
将做了符号扩展的双字传送到四字
把%eax符号扩展到%rax

压入和弹出栈数据

指令效果描述
pushq S

popq D
R[%rsp] ← \leftarrow R[%rsp]-8;
M[R[%rsp]] ← \leftarrow S

D ← \leftarrow M[R[%rsp]];
R[%rsp] ← \leftarrow R[%rsp]+8
将四字压入栈


将四字弹出栈

这两个操作都会修改%rsp的值

算术和逻辑操作

指令效果描述
leaq S, DD ← \leftarrow &S加载有效地址
该指令实际上是movq指令的变形,
它的指令形式是从内存读数据到寄存器,
但实际上它没有引用内存,而是将有效地址
写入到目的操作数,
比如 leaq 7(%rdi,%rsi,4),%rax
会把%rax设置为 %rdi+4*%rsi+7
INC D
DEC D
NEG D
NOT D
D ← \leftarrow D + 1
D ← \leftarrow D - 1
D ← \leftarrow -D
D ← \leftarrow ~D
ADD S,D
SUB S,D
IMUL S,D
XOR S,D
OR S,D
AND S,D
D ← \leftarrow D + S
D ← \leftarrow D - S
D ← \leftarrow D * S
D ← \leftarrow D ^ S
D ← \leftarrow D | S
D ← \leftarrow D & S
SAL k,D
SHL k,D
SAR k,D
SHR
D ← \leftarrow D << k
D ← \leftarrow D << k
D ← \leftarrow D >>(算数) k
D ← \leftarrow D >>(逻辑) k
左移
左移(等同于SAL)
算术右移
逻辑右移

注意,ADD S,D 由四条加法指令组成,即 addb, addw, addladdq,其他指令也是如此

Intel把16字节的数称为八字(oct word)。下面是一些特殊的指令:

指令效果描述
imulq S
mulq S
R[%rdx]:R[%rax] ← \leftarrow S * R[%rax]
R[%rdx]:R[%rax] ← \leftarrow S * R[%rax]
有符号乘法,结果高64位放在%rdx,低64位放在%rax
无符号乘法,结果高64位放在%rdx,低64位放在%rax
cltoR[%rdx]:R[%rax] ← \leftarrow 符号拓展(R[%rax])将%rax符号拓展为8字,高64位放在%rdx
idivq

divq
R[%rdx] ← \leftarrow (R[%rdx]:R[%rax]) mod S
R[%rdx] ← \leftarrow (R[%rdx]:R[%rax]) ÷ \div ÷ S

R[%rdx] ← \leftarrow (R[%rdx]:R[%rax]) mod S
R[%rdx] ← \leftarrow (R[%rdx]:R[%rax]) ÷ \div ÷ S
有符号除法,将%rdx作为被除数的高64位,%rax作为被除数的低64位

无符号除法,将%rdx作为被除数的高64位,%rax作为被除数的低64位

控制指令

条件码

CPU维护着一组单个位的条件码寄存器,它们描述了最近的算数或者逻辑操作的属性,可以检查这些寄存器来执行条件分支指令。最常用的条件码有:

  • CF:进位标志,最近的操作使最高位产生了进位,可用于检查无符号操作的溢出
  • ZF:零标志,最近的操作得出的结果为0
  • SF:符号标志,最近的操作得到的结果为负数
  • OF:溢出标志,最近的操作导致一个补码溢出(正溢出获负溢出)

算术和逻辑操作列出的指令中,除了leaq,其他指令都会修改条件码寄存器

除了算数和逻辑操作指令可以改变条件码寄存器,下面的指令也可以改变:

指令基于描述
CMP S1,S2S2 - S1比较,根据 S2 - S1 的值来设置条件码寄存器
TEST S1,S2S1 & S2根据 S1 & S2 (逻辑与,不是按位与)的值来设置条件码寄存器

访问条件码

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

  • 更具条件码的某种组合,将一个字节设置为0或者1
  • 根据条件码进行跳转
  • 有条件地传送数据

对于第一种情况,将这一整类指令称为SET指令

指令同义名效果设置条件
sete D
setne D
setz
setnz
D ← \leftarrow ZF
D ← \leftarrow ~ZF
相等/零
不等/非零
sets D
setns D
D ← \leftarrow SF
D ← \leftarrow ~SF
负数
非负数
setg D
setge D
setl D
setle D
setnle
setnl
setnge
setng
D ← \leftarrow ~(SF^OF) & ~ZF
D ← \leftarrow ~(SF^OF)
D ← \leftarrow SF^OF
D ← \leftarrow SF^OF | ZF
有符号大于
有符号大于等于
有符号小于
有符号小于等于
seta D
setae D
setb
setbe
setnbe
setnb
setnae
setna
D ← \leftarrow ~CF & ~ZF
D ← \leftarrow ~CF
D ← \leftarrow CF
D ← \leftarrow CF | ZF
无符号大于
无符号大于等于
无符号小于
无符号小于等于

跳转指令

指令同义名跳转条件描述
jmp Label
jmp *Operand
1
1
直接跳转
间接跳转
je Label
jne Label
jz
jnz
ZF
~ZF
相等
不相等
js Label
jns Label
SF
~SF
负数
非负数
jg Label
jge Label
jl Label
jle Label
jnle
jnl
jnge
jng
~(SF^OF) & ~ZF
~(SF^OF)
SF^OF
SF^OF |ZF
有符号大于
有符号大于等于
有符号小于
有符号小于等于
ja Label
jae Label
jb Label
jbe Label
jnbe
jnb
jnae
jna
~CF & ~ZF
~CF
CF
CF | ZF
无符号大于
无符号大于等于
无符号小于
无符号小于等于

条件传送指令

指令同义名跳转条件描述
cmove S,R
cmovne S,R
cmovz
cmovnz
ZF
~ZF
相等
不相等
cmovs S,R
cmovns S,R
SF
~SF
负数
非负数
cmovg S,R
cmovge S,R
cmovl S,R
cmovle S,R
cmovnle
cmovnl
cmovnge
cmovng
~(SF^OF) & ~ZF
~(SF^OF)
SF^OF
SF^OF |ZF
有符号大于
有符号大于等于
有符号小于
有符号小于等于
cmova S,R
cmovae S,R
cmovb S,R
cmovbe S,R
cmovnbe
cmovnb
cmovnae
cmovna
~CF & ~ZF
~CF
CF
CF | ZF
无符号大于
无符号大于等于
无符号小于
无符号小于等于

转移控制

指令描述
call Label
call *Operand
ret
过程调用
过程调用
从过程调用中返回
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值