关于LEA指令
堆栈种分配的局部变量所谓的“标号”,你以为是什么?(都是那些该死的宏惹的祸,大家要都是老老实实写代码,就不会有这些疑问了)。
比如你用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...”了。