摘要: 做了个DNS查询有关的程序,用到了DnsQuery和DnsRecordListFree这2个函数,拿到导师那里一用,竟然出现一个对话框,“无法将函数DnsFree定位于动态连接库Dnsapi.dll上”...
阅读全文
现在真的进入.NET时代了吗?貌似人人都说现在是.NET时代。但是真正用.NET写的程序又有多少呢?目前我就发现几个,也就是Visual Studio系列的 2003 2005 2008之类的IDE,但是他们的核心,编译器cl.exe、连接器link.exe是什么写的呢?应该还是C语言吧,要么是汇编,呵呵。虽然我不喜欢.NET但是.NET的开发效率是很高的,但是运行效率确实不怎么样。我AMD 2.4G的CPU(超频的,不过是单核)、2G内存、硬盘是2块250G RAID0,机器3年前配的,可能老了点,开个VS2008也要20秒左右,确实运行效率不高。但是我相信随着CPU、内存、硬盘速度的提高,.NET优势会明显的。对于以后的趋势,暂且抛开unix、linux不谈,我想就是类似VS这样,界面之类的窗口框架用.NET写,然后核心部分,还是C/C++的天下。所以C/C++永远不会落伍,除非哪天微软用.NET写个操作系统出来。而为什么linux方向的发展在中国远远不如国外呢?是不是Apache真的不如IIS?MySQL真的不如MSSQL?PHP5真的如不ASPX?我想肯定不是,至少我用下来的感觉就是这样,初中时候我开始学做网页用php,用下来apache确实比IIS要舒服很多,体积也小。但为什么这么多开源的软件国人不去用呢?因为我国都是D版,我国人普遍认为所有软件都是免费的,而MS这个品牌被很多人都认可的(我小学时候就接触过bill gates的书),人们总想着MS的东西和其他开源的一样,全是免费的,那当然就看品牌咯,MS是耳熟能详,当然选择他。
中国人接受新事物是比较快的,很喜欢尝个新鲜,就造成了市面上全是.NET/JAVA的培训之类的,其实并不是趋势变了,而是人在变,一些人认为.NET/JAVA好,就去向那方向发展,这样的话又有很多新东西要去学,他们就说IT行业有学不完的东西。其实只要学精学专也不影响什么的。鲁迅的一句话“物以稀为贵”,确实没错,但是我们往往忽视了这点,总想“大众化”,“随大流”,这样往往丧失了很多机会。杂而不专是很忌讳的,我感触颇深,自己小学开始接触C语言,初中又开始做网页,PHP+MYSQL之类的,高中又开始学FLASH动画和PHOTOSHOP,大学一开始玩了2年,无所事事,后来开始研究网游私服源代码,这又回到C/C++上,闹到现在大学快毕业一事无成。
就算.NET再怎么发展,我认为一个大软件的核心还是C/C++写的,一个操作系统的核心部分也是C/C++写的,硬件驱动程序也是C/C++,那么我们如果想一直在C/C++领域发展,就必须深入底层,深入核心,把界面这种简单的工作交给.NET去做吧!
PS:据小道消息透露:今年是病毒年,各种病毒已经进入ring0。你准备好了吗?
今天突发奇想想玩玩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,对软件加密有所帮助
现在这形势是越底层越吃香阿,为了让自己更好的向底层发展,尽量让自己使用C的函数,因为底层全是C语言,不是C++,更不是VC++,使用FILE* fp;而不是CFile file;使用strcpy,strcmp,strcat而不是CString之类的