addr与offset

addr可以处理局部变量而   offset   则不能。局部变量只是在运行时在堆栈中分配内存空间。而   offset   则是在编译时由编译器解释,这显然不能用offset   在运行时来分配内存空间。编译器对   addr   的处理是先检查处理的是全局还是局部变量,若是全局变量则把其地址放到目标文件中,这一点和   offset   相同,若是局部变量,就在执行   invoke   语句前产生如下指令序列:    
  lea   eax,   LocalVar  
  push   eax  
  因为lea指令能够在运行时决定标号的有效地址,所以有了上述指令序列,就可以保证   invoke   的正确执行了。      
  回复人: cui(蚊子王) (2001-9-2   17:06:36)     得10分    
  vBin(彬)说的很对,这是用lea(addr事实上就是lea语句)的一个理由;另一个理由是:  
  假设要bx+10h->bx但又不想影响flag那就只能用lea   bx,[bx+10h]了。       
  回复人: thickhead_cat(笨猫) (2001-9-3   15:39:10)     得10分    
  我不同意楼上的说法:  
   
  其实,  
  1、汇编里有很多功能,能用不同的指令实现,这一点也不奇怪  
  2、lea是cpu的指令,而mov   ax,offset   xxx   只是我们利用编译器的offset自动计算的功能  
  3、lea指令远在exe文件产生前就有了,那时顶多只有com文件,所以它和执行时计算偏移量无关的!      
  回复人: totkid(皮耶德) (2001-9-3   16:26:57)     得0分    
  对不起……我还是有一些不解  
  局部变量?  
  如果我要  
  lea   eax,LocalVar  
  那么我是通过什么寻址方式找到LocalVar的呢???  
  既然能通过寻址方式找到该变量  
  为什么不直接把“地址”送到该寄存器呢??  
  还有……lea指令能够在运行时确定标号的有效地址,请问这是什么意思呢?  
  我记得标号都是在编译期就被转化为某个确定的偏移了,然后连接时期确定段值  
  这一切都应该是在运行期之前就确定的东西呀!  
   
  还有,关于在堆栈中运行时分配的变量,如果我们为它设定了一个标号,那么我们  
  要lea它的地址的时候,是怎么知道我们要lea的是某个地址的变量呢?既然我们若  
  可以指定——“就lea这个变量的地址给我看”,那么我们起码要知道到底是哪个变量,  
  那么我们到底怎么指定呢??标号是根本不存在于运行时的程序中的,那么我们肯定应该是  
  指定它的地址了,既然能指定它的地址……那么直接把它的地址发到某个寄存器不就得了?  
   
  cui的那个例子使我开了一些窍,不过,难道lea只是用在这些窍门上吗?  
   
  我太苯了!不好意思!      
  回复人: azuo_lee() (2001-9-3   17:16:16)     得15分    
  堆栈种分配的局部变量所谓的“标号”,你以为是什么?(都是那些该死的宏惹的祸,大家要都是老老实实写代码,就不会有这些疑问了)。  
  比如你用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]      
  回复人: CNer(......) (2001-9-3   17:21:26)     得10分    
  我补充一点:在tasm中,lea指令,很多都是替换成等效的mov   offset指令的。      
  回复人: cui(蚊子王) (2001-9-3   17:34:49)     得15分    
  关于局部变量我还是举个例子吧:  
  比如以下的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...”了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值