随笔-16  评论-116  文章-0  trackbacks-0
转载请注明出处http://www.cppblog.com/greatws/archive/2008/04/22/47783.html

今天突发奇想想玩玩C的内联汇编,以前也经常在DOS下玩debug,那就先整个最简单的MessageBox玩玩咯
网上找了一段代码
 char* lpCaption="111";
 
char* lpText="222";

_asm  
 
{  
  push MB_OK  
  lea eax,lpCaption 
  push eax 
  lea eax,lpText
  push eax 
  push NULL
  call dword ptr [MessageBoxA]  
}


于是在VC9下建了一个Dialog工程,MFC,然后在一个Button事件下加入这段代码,鼠标在MessageBoxA上放了下,一看CWnd::MessageBox...3个参数,而上面代码中push了4个参数,汗一个,那就去掉最后一个参数句柄吧,编译---运行---点一下Button,居然标题和内容都是乱码。。。回到VC开始调试,看看问题出在哪里。进入反汇编窗口,看lpCaption的值是0x00424da4,F8单步(为了和OD一致,我改成了F8),执行lea eax,lpCaption ,一看eax的值,吓一跳,变成0x0012f878...汗一个,怎么就变成这个了。仔细一想,lpCation是一个char*指针类型, lpCaption指向的地址是0x00424da4,当然lpCaption也是存在内存某一地址中的,估计lea把lpCation所在的内存地址送到eax,没有将其中的值送到eax,于是改成mov试试
_asm  
 
{  
  push MB_OK  
  mov eax,lpCaption 
  push eax 
  mov eax,lpText
  push eax 
  call dword ptr [MessageBoxA]  
}



这下就没有问题了,真汗,从中学一直被忽悠到大学....

接下来来测试一C内联asm和C下那个效率更高,为了方便查看,来直接调用API的MessageBox,但是不能call dword ptr [::MessageBoxA],那就用函数指针吧- -
typedef int (__stdcall* messageboxfunc)(HWND,LPCTSTR,LPCTSTR,UINT);
 
char* lpCaption="111";
 
char* lpText="222";
 messageboxfunc api_messagebox
=::MessageBoxA;
 _asm  
 
{  
  
  push MB_OK  
  mov eax,lpCaption 
  push eax 
  mov eax,lpText
  push eax 
  push NULL
  call dword ptr [api_messagebox]  
  
 }

//写一个直接调用MessageBox的函数,等下用OD调试看看代码情况
api_messagebox(NULL,lpText,lpCaption,MB_OK);



OD调试的截图
第一行是我的::MessageBox函数指针,到call dword ptr [ebp-4]用了9行...用了29个字节,mov-mov-mov-push-mov-push-mov-push-push,好花啊,而直接使用函数调用API(后那个call esi,esi在上面就是mov esi,dword ptr [<&USER32.MessageBoxA>],函数指针嘛),4个连续的push外加一个call则只用了14个字节,my god!!!!!C内联asm反而效率低?还是编译器不对这些代码进行优化?成为传说中的“花指令”?

由此可见,VC的代码优化非常的好,一般不要轻易用内联asm,除非是超高手或者迫不得已~~HOHO,但是用C内联汇编写一些花指令还是不错的,比如说把jmp 00420000写成
jz 00420000
nop
nop
nop
nop
jnz 00420000

HOHO,对软件加密有所帮助
by gratws
posted on 2008-04-22 01:39 greatws 阅读(6141) 评论(12)  编辑 收藏 引用

评论:
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-22 09:15 | 梦在天涯
haha!超级高手!期待更多的!  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-22 09:24 | xxx
没有学好汇编,不是被忽悠  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-22 09:37 | 陈梓瀚(vczh)
lea是Load Efficient Address啊,跟Mov咋能一样……  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-22 09:46 | lonkil
呵呵,lea是传地址,mov是赋值.

内联那段分析的有道理,学习了.以后写代码的时候要主意了.
  回复  更多评论
  
# 关于内联指令不是很明白 2008-04-22 22:15 | herculesinchina
关于反汇编代码写的不清楚,看不大懂你的意思。
若说内联效率有时低,那可能是因为编译器要在内联指令的前后为某些寄存器赋值,若你的内联代码较少,则编译器的准备工作就显得多了。  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-23 13:10 | 空明流转
lea和mov差远了去了。。。  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-23 13:48 | faint
lea ,mov大学学的时候老师就说了嘛,“要注意区分”  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-24 20:59 | AMXTSHMF
= =!  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-04-27 19:47 | greatws
@faint
我老师怎么没给我说过...  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-08-29 10:44 | xufan
好想学喔..可以教我吗  回复  更多评论
  
# re: 被忽悠了,一直以为lea和mov指令差不多的,今天算是知道了,顺便测试了下C内联汇编的效率 2008-11-12 09:21 | 似水之心
自学的汇编,书上没有lea,找到这儿来了,原来这个样子,谢谢了

改个错字  回复  更多评论
  
# shi 2010-08-23 16:35 | uk dress
That's good  回复  更多评论
  

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