作用将源操作数的值复制到目的操作数;这里规定源和目标操作不能都指向存储器位置,从一个存储器位置复制到另一个存储器位置需要两条指令,第一条指令将源操作数加载到寄存器,第二条将寄存器的值写到目标位置
指令                               动作                                        描述
MOV S,D                    D<-S                                        传送
Movb                          传送字节 
Movw                          传送字
Movl                           传送双字
MOVS S,D                 D<-S(符号扩展)                        传送扩展字节
Movsbw                      传送做了符号扩展字节到字 
Movsbl                        传送做了符号扩展字节到双字
Movswl                       传送做了符号扩展字到双字
MOVZ S,D                 D<-S(零扩展)                           传送扩展字节
Movzbw                      传送做了符号扩展字节到字 
Movzbl                        传送做了符号扩展字节到双字
Movzwl                        传送做了符号扩展字到双字
Push  S                       R[%esp]<-R[%esp]-4                 双字压栈
                                                                              M[R[%esp]]<-S 
Popl D                         D<-M[R[%esp]];                        双字出栈
                                                                              R[%esp]<-R[%esp]+4
 
                     
Movs和Movz都是将较小的数值复制较大的数据位置中。符号扩展的目标位置的高位都是源数值的高位填充,零扩展的目标位置的高位全部用零填充。
 
Mov指令组合(5种):
Movl $0x2050,%eax                立即数----寄存器      4字节
Movw %bp,%sp                    寄存器---寄存器      2字节
Movb (%edi,%ecx),%ah              存储器---寄存器      1字节
Movb $-17,(%esp)                  立即数---存储器       1字节
Movl %eax,-12(%ebp)              寄存器---存储器      4字节
 
Movb、movsbl、movzbl的差别:比如:%dh=ab,%eax=23456789
Mov     %dh,%al                %eax=234567ab
Movsbl   %dh,%eax              %eax=fffffffab
Movzbl   %dh,%eax              %eax=000000ab
 
Push1把数据压栈,popl是把数据出栈
IA32的栈是向低地址增长,因此压栈是减少栈指针(寄存器%esp)的值,并把数据放到存储器中;
出栈是从存储器中读(数据),并增加栈指针的值。
Pushl %ebp等价以下指令:subl $4,%esp   movl %ebp,(%esp)
两者区别pushl指令编码是1个字节,上面两条指令是6个字节
Popl %edx等价以下指令:movl (%esp),%eax    addl $4,%esp
Esp总是指向栈顶的指针,ebp是存取栈顶的指针
 
int change(int* xp,int y)
{
 int x = *xp;
 *xp   = y;
 
 return x;
}
这个函数的汇编代码如下:
change:
         pushl         %ebp
         movl %esp, %ebp
         subl $16, %esp
         movl 8(%ebp), %eax   取形参,第N个形参在栈上的位置为(N+1)*4+%ebp
         movl (%eax), %eax     把形参指向的地址单元的值赋给%eax
         movl %eax, -4(%ebp)
         movl 8(%ebp), %edx
         movl 12(%ebp), %eax
         movl %eax, (%edx)
         movl -4(%ebp), %eax
         leave
         ret
         .size change, .-change
从上面的代码中我们可以看到指针的实质就是地址,间接应用不过就是将该指针放到一个寄存器,然后在存储器中使用这个寄存器;
局部变量通常保存在寄存器中,寄存器访问比存储器要快得多s
 
上面是没有优化的汇编代码,在编译的时候加上-O2,汇编指令如下:
change:
 7 | pushl|%ebp
 8 | movl| %esp, %ebp
 9 | movl| 8(%ebp), %edx
 10 | movl| 12(%ebp), %ecx
 11 | movl| (%edx), %eax
 12 | movl| %ecx, (%edx)
 13 | popl| %ebp
 14 | ret
 15 | .size|change, .-change
 16 | .p2align 4,,15
 
开启了-O2之后,gcc大量使用寄存器,极大的减少了多余的寻址操作