Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 397, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

linux汇编指令之数据传输指令mov

作用将源操作数的值复制到目的操作数;这里规定源和目标操作不能都指向存储器位置,从一个存储器位置复制到另一个存储器位置需要两条指令,第一条指令将源操作数加载到寄存器,第二条将寄存器的值写到目标位置

指令                               动作                                        描述

MOV SD                    D<-S                                        传送

Movb                          传送字节

Movw                          传送字

Movl                           传送双字

MOVS SD                 D<-S(符号扩展)                        传送扩展字节

Movsbw                      传送做了符号扩展字节到字

Movsbl                        传送做了符号扩展字节到双字

Movswl                       传送做了符号扩展字到双字

MOVZ SD                 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

 

                    

MovsMovz都是将较小的数值复制较大的数据位置中。符号扩展的目标位置的高位都是源数值的高位填充,零扩展的目标位置的高位全部用零填充。

 

Mov指令组合(5)

Movl $0x2050,%eax                立即数----寄存器      4字节

Movw %bp,%sp                    寄存器---寄存器      2字节

Movb (%edi,%ecx),%ah              存储器---寄存器      1字节

Movb $-17,(%esp)                  立即数---存储器       1字节

Movl %eax-12(%ebp)              寄存器---存储器      4字节

 

Movbmovsblmovzbl的差别:比如:%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大量使用寄存器,极大的减少了多余的寻址操作

posted on 2013-01-22 20:28 Benjamin 阅读(3840) 评论(0)  编辑 收藏 引用 所属分类: (反)汇编


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理