x86-64的数据传送指令

前言

本篇文章介绍x86-64的数据传送指令,数据指令大类上分为三个

  • mov
  • pushq和popq
    其中,mov是比较复杂的指令合集

mov

顾名思义,mov指令是用于数据的传输,数据的传输方式有这么几种:

  • 立即数传给寄存器
  • 立即数传给内存
  • 寄存器传给内存
  • 内存传给寄存器
  • 寄存器传给寄存器
  • 内存传给内存:需要注意的是,x86-64不允许直接从内存传递到内存,这个方式需要两条指令实现,即从内存--寄存器,然后寄存器--内存

最基本的指令MOV

MOV指令是最基本的指令,该指令集有五个具体的指令:

  • movb:move byte,传送字节
  • movw:move word,传送字
  • movl:move long word,传送双字
  • movq:move quad,传送四字
  • movabsq:move abs quad,传送绝对四字
    这里需要值得注意和解释的几点:
  1. MOV指令的使用方式位 MOV S D,S是源操作数,D是目的操作数,是从S–>D,这个跟后面介绍的运算操作符是不一样的
  2. movq当S是立即数的时候,只能使用32位补码数(有符号操作数),然后符号位扩展为64位,符号位扩展的意思就是高32位全部用符号位代替,鉴于此,才有了movabsq,movabsq直接能使用64位立即数。
  3. 无论是S还是D,如果是寄存器,寄存器的名称代表的字节数必须与指令传送的字节数一致,比如movb如果传送数字1给%rax,只能写成movb $1,%al
  4. 通常情况下,MOV指令只会更新目的操作数指定的那些寄存器字节或内存位置。唯一的例外是movl指令以寄存器作为目的时,它会把该寄存器的高位4字节设置为0

以0扩展的指令MOVZ

MOVZ是指数据从小字节传送到大字节时使用的传送指令,Z的是zero的意思,代表高位全部用0代替。
MOVZ有五个具体的指令,分别为:

  • movzbw:1字节byte数据传给2字节word数据
  • movzbl:1字节byte数据传给4字节long word数据
  • movzwl:2字节word数据传给4字节long word数据
  • movzbq:1字节byte数据传给8字节quad word数据
  • movzwq:2字节word数据传给8字节quad word数据

这里需要值得注意和解释的几点:

  1. 源操作数可以是寄存器或者内存数据,目的操作数只能是寄存器
  2. 没有从4字节long word数据传给8字节quad word数据的指令,因为我们前面讲过movl的时候,如果目标操作数是寄存器,就像movz指令集介绍的那样,寄存器的高位4字节会设置为0,相当于做了0扩展,所以不需要这个指令

以符号扩展的指令MOVS

MOVS是指数据从小字节传送到大字节时使用的传送指令,S的是symbol符号的意思,代表高位全部用符号位代替。
MOVS有五个具体的指令,分别为:

  • movsbw:1字节byte数据传给2字节word数据
  • movsbl:1字节byte数据传给4字节long word数据
  • movswl:2字节word数据传给4字节long word数据
  • movsbq:1字节byte数据传给8字节quad word数据
  • movswq:2字节word数据传给8字节quad word数据
  • movslq:4字节long word数据传给8字节quad word数据
  • cltq:寄存器eax符号位扩展到rax

这里需要值得注意和解释的几点:

  1. 源操作数可以是寄存器或者内存数据,目的操作数只能是寄存器
  2. cltq指令没有操作数,就是将eax寄存器符号位扩展到rax,比如
movl $0xFFFFFFFF , %eax
cltq

第一条指令将rax寄存器设置为00000000FFFFFFFF
第二条指令将rax寄存器设置为FFFFFFFFFFFFFFFF

几个例子

1. movb $OxF, (%ebx) 
2. mov1 %rax, (%rsp) 
3. movw (%rax) ,4(%rsp) 
4. movb %al,%sl
5. movq %rax, $0×123 
6. mov1 %eax,%rdx 
7. movb %si, 8(rbp)

这上面的每个指令都是错误的:

  1. 立即数的位数不对
  2. %rax的字节数和movl不匹配
  3. 不能从内存传送数据到内存
  4. 没有sl寄存器,可参考x86-64汇编指令支持的通用目的寄存器
  5. 目的操作数不能是立即数,只能是寄存器或者内存引用
  6. 目的操作数rdx和movl不匹配,应该使用edx
  7. 源操作数si和movb不匹配,用该使用sil

pushq和popq

入栈指令,更新栈指针,并且将一个四字节数据入栈
出栈指令,将一个四字节数据出栈,并且更新栈指针
内存中的程序运行栈是一种先进后出的数据结构,寄存器rsp指向的就是栈指针,栈的内存布局有这样的特点,从内存的高地址向低地址排列,也就是栈底在最高位,栈顶在最低位,所以入栈,rsp的值减小,出栈,rsp的值增大

pushq S的执行过程是这样的:

subq $8,%rsp
movq S,(%rsp)

popq S的执行过程是这样的:

movq (%rsp),S
addq $8,%rsp

虽然效果一样,但是pushq和popq指令更简洁

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值