关于LEA指令(单周期就可以做简单的算术计算)

时间:2022-04-11 00:52:43

堆栈种分配的局部变量所谓的“标号”,你以为是什么?(都是那些该死的宏惹的祸,大家要都是老老实实写代码,就不会有这些疑问了)。   
   比如你用local在栈上定义了一个局部变量LocalVar,你知道实际的指令是什么么?一般都差不多像下面的样子:   
   push    ebp   
   mov    esp,    ebp   
   sub    esp,    4   
   现在栈上就有了4各字节的空间,这就是你的局部变量。   
   接下来,你执行mov    LocalVar,    4,那么实际的指令又是什么?是这样:   
   mov    dword    ptr    [ebp-4],    4   
   于是,这个局部变量的“地址”就是ebp-4——显然,它不是一个固定的地址。现在需要将它的“地址”作为参数传给某个函数,你这样写:   
   invoke/call    SomeFunc,    addr    LocalVar   
   实际生成的指令是:   
   lea    eax,    [ebp-4]   
   push    eax   
   call    SomeFunc   
   当然,你也可以写成:   
   mov    eax,    ebp   
   sub    eax,    4   
   push    eax   
   call    SomeFunc   
   看到了,这里多了一条指令。这就是lea的好处。

于是,lea又多了一个非常美妙的用途:作简单的算术计算,特别是有了32位指令的增强寻址方式,更是“如虎添翼”:   
   比如你要算EAX*4+EBX+3,结果放入EDX,怎么办?   
   mov    edx,    eax   
   shl    edx,    2   
   add    edx,    ebx   
   add    edx,    3   
   现在用lea一条指令搞定:   
   lea    edx,    [ebx+eax*4+3]

//------------------------------------

关于局部变量我还是举个例子吧:   
   比如以下的C/C++函数(c调用方式):   
   void    abc(void){   
         int    a=0x1234;   
         efg(&a);   
   }   
   翻译成对等的ASM代码:   
   _abc    proc    near   
             push    ebp   
             mov      ebp,esp   
             sub      esp,4h   
             ;   
             lea      eax,[ebp-4h]   
             mov      [eax],1234h   
             push    eax   
             call    _efg   
             add      esp,4h   
             ;   
             mov      esp,ebp   
             pop      ebp   
             ret   
   _abc    endp   
   这时栈的情况如下:   
   ----------    <----esp   
   a   
   ----------    <----ebp   
   old    ebp   
   ----------   
   ret    address   
   ----------   
   这时要取得a的地址,那只能用"lea      eax,[ebp-4h]"而不能用“mov    offset...”了。

http://blog.csdn.net/yiruirui0507/article/details/6193140