上一篇博客 咱们介绍了几种数据传送指令,包括MOV,MOVS,MOVZ,PUSH和POP等,理解起来也不算难。本篇博客咱们来接着看汇编语言的算术与逻辑运算指令,算术无非就是加减乘除,而逻辑运算也就是与或非,移位等操做。下面这张图是汇编里面的算术和逻辑操做:html
上面除了 leal(加载有效地址)指令一般用来执行简单的算术操做,其他的指令都是标准的一元或者二元操做,下面咱们分别来介绍这几个指令操做。htm
leal 指令也称为加载有效地址(load effective address)指令,它其实是 movl 指令的变形。它的指令形式是从存储器读数据到寄存器,但实际上它根本没有引用存储器。blog
它的第一个操做数看上去是一个存储器引用,但该指令并非从指定的位置读取数据,而是将有效地址写入到目的操做数,相似于 C 语言的取地址操做符“&”。另外就是做普通的算术运算。内存
leal 当即数,寄存器get
这类指令就是将当即数装载至寄存器,好比 leal $0x01,%eax 这种状况下 和 movl $0x01,%eax 的效果是等价的博客
leal 地址,寄存器变量
leal指令的做用是将地址加载到寄存器,对于leal S,D而言,就是实现了 &S –> D 的功能引用
leal S, D 结果是&S -> Dim
movl S,D 结果是S -> D数据
通用的操做咱们就不讲了,这里讲一下取地址操做,好比对于leal 4(%edx,%edx,4),%eax这条指令来说,咱们假设%edx寄存器的值为x的话,那么这条指令的做用就是将 4 + x + 4x = 5x + 4赋给%eax寄存器。它和mov指令的区别就在于,假设是movl 4(%edx,%edx,4),%eax这个指令,它的做用是将内存地址为5x+4的内存区域的值赋给%eax寄存器,而leal指令只是将5x+4这个地址赋给目的操做数%eax而已,它并不对存储器进行引用的值的计算。
为了更好的表示这条指令的效果,这里简单的画个图来表示这一过程。咱们假设下图是执行指令以前,寄存器和存储器的状态。
下面的几幅图均引用:http://www.cnblogs.com/zuoxiaolong/p/computer16.html 我的以为解释的很是形象。
能够看到,此时在存储器中,地址为5x+4的区域的值为1000。那么此时如果进行movl 4(%edx,%edx,4),%eax操做,很显然,%eax的值应该为1000,也就是下图。
可是若是进行leal 4(%edx,%edx,4),%eax操做的话,%eax的值就不是1000了,由于leal指令不会去取存储器当中的值,所以寄存器%eax的值应该是5x+4。
试想一下,假若在地址为5x+4的位置存储的是变量i,那么其实这条指令就至关于&i操做,这也就是C语言当中的&取地址操做的汇编级作法。
此外,它还能够简单的描述普通的算术操做,好比假如寄存器 %edx 的值为 x,那么指令 leal 7 (%edx,%edx,4),%eax。 这表示的意思是设置寄存器 %eax 的值为 7+x+4x=5x+7。这里的leal指令根本与有效地址无关,可是须要注意的是目的操做数必须是寄存器。
这四个指令的格式以下:
这四个指令都是一元操做,即它们都只有一个操做数,便是源也是目的。这个操做数能够是寄存器,也能够是存储器。
好比: incl (%esp) 会使栈顶的 4 字节元素加 1。能够联想到 C 语言的自增(++)或者自减(--)
这一组指令格式以下:
它们都是二元操做,其中第二个操做数便是源又是目的,咱们能够联想到 C 语言的 x += y。
第一个操做数能够是当即数、寄存器或存储器,第二个操做数能够是寄存器或存储器位置。不过和 movl 指令同样,两个操做数不能同时是存储器位置。
移位操做,指令格式以下:
第一个操做数是移位量,SAL 和 SHL 都是左移指令,效果是同样的,移动几位,右边补上几位0;右移指令不一样,算术右移 SAR 是补上符号位,即右边的第一位;逻辑右移 SHR 是补上 0 。
移位的目的操做数能够是一个寄存器或是一个存储器位置。