数据传送指令
程序中最频繁使用的指令莫过于将一个数据从一个位置复制到另一个位置的指令。操作数标识的通用性使得一条简单的数据传统指令能够完成在许多机器中要好几条不同指令才能完成的功能。
一、基本用法
下图中列出了最简单形式的数据传送指令——MOV类。这些指令把数据从源位置复制到目的位置,不做任何变化。MOV类由四条指令组成:movb、movw、movl和movq。这些指令都执行同样的操作;主要区别在于他们操作的数据大小不同,分别是1、2、4和8字节。
| 指令 | 效果 | 描述 |
|---|---|---|
| MOV S, D | S → D | 传送 |
| movb | 传送字节 | |
| movw | 传送字 | |
| movl | 传送双字 | |
| movq | 传送四字 | |
| movabsq I, R | I → R | 传送绝对的四字 |
源操作数指定的是一个立即数,存储在寄存器中或者内存中。目的操作数指定一个位置,要么是一个寄存器 或者是一个内存地址 。
x86-64加了一条限制,传送指令的两个操作数不能都指向内存地址。将一个内存位置复制到另一个内存位置需要两条指令——第一条指令将源值加载到寄存器中,第二条将该寄存器值写入目的位置。这些指令的寄存器可以是16个寄存器有标号部分中的任意一个。寄存器部分的大小必须与指令最后一个字符(‘b’,’w’,‘l’或‘q’)指定的大小匹配大多数情况中,mov指令只会更新目的操作数指定的那些寄存器字节或者内存位置。唯一的例外是movl指令意寄存器作为目的时,它会把该寄存器的高四字节设置为0(x86-64的惯例,任何为寄存器生成32位值得指令都会把该寄存器的高位部分置成0)。
下面的MOV指令示例给出了源和目的类型的五种可能的组合。记住,第一个是源操作数,第二个是目的操作数:

讯享网
二、将较小的源值复制到较大的目的
下图movz类中的指令把数据从源(在寄存器或内存中)复制到目的寄存器。剩余的字节填充为0,而movs类中的指令通过符号扩展来填充,把原操作的最高位进行复制。
从下图可以看到,零扩展数据传送指令。这些指令以寄存器或者内存地址作为源,以寄存器作为目的。每条指令名字的最后两个字符都是大小指示符:第一个字符指定源的大小,而第二个指明目的的大小。

从下图可以看到,符号扩展数据传送指令。MOVS指令以寄存器或内存地址作为源,以寄存器作为目的。cltq指令只作用于寄存器%eax和%rax作为目的。

特别注意 mov 和 lea
lea指令变种(按大小分类):
leaw #2个字节
leal #4个字节

leaq #8个字节
lea的用法:
leaq a(b, c, d), %rax
首先lea指令是mov指令的变种,据说,lea指令是x86体系结构中,是一条最古老但是从某个方面来讲又是最神奇的指令。
表面上看,它做的事情非常简单,根据括号里的源操作数来计算地址,然后把地址加载到目标寄存器中。
例如:leaq a(b, c, d), %rax 先计算地址a + b + c * d,然后把最终地址载到寄存器rax中。
那这样的完全可以把它当作乘法指令使用。
一点思考:mov可以对应于c语言的赋值语句操作,而lea可以对应于指针的操作
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/18700.html