最新消息:

NSIS脚本源码分析: 如何判断CPU平台类型

nsis 永恒心锁 3302浏览 0评论

做安装程序时,有时需要支持多个CPU平台。Windows下支持的CPU平台一般有三大类:x86, x64和ia64。

其中,x86就是我们最常用的32位平台,x64则是64位的x86平台,ia64比较特殊,它只存在于Intel Itanium系列芯片中。

好了,下面上源码了:

[php] view plaincopy

  1. ;
  2. ; Get the native system info
  3. ;
  4. System::Alloc 32
  5. Pop $0
  6. System::Call “Kernel32::GetNativeSystemInfo(i) v (r0)”
  7. System::Call “*$0(&i2 .r1)”
  8. System::Free $0
  9. StrCmp $1 9 0 +2
  10. DetailPrint PROCESSOR_ARCHITECTURE_AMD64
  11. StrCmp $1 6 0 +2
  12. DetailPrint PROCESSOR_ARCHITECTURE_IA64
  13. StrCmp $1 0 0 +2
  14. DetailPrint PROCESSOR_ARCHITECTURE_INTEL
  15. StrCmp $1 0xffff 0 +2
  16. DetailPrint PROCESSOR_ARCHITECTURE_UNKNOWN

看到上面的代码是否有点云里雾里的感觉?反正第一眼看过去,我的感觉就是这样。不过,不要急,慢慢地一句一句地分析,自然会将它搞明白的。

首先看前两句:

[php] view plaincopy

  1. System::Alloc 32
  2. Pop $

System是NSIS的一个标准插件,可以在NSIS安装目录的Plugins子目录下可以找到,System.dll是也。System是NSIS中 的一个很重要的插件,安装中的很多高级功能都是通过它来实现的。System::Alloc也就是调用System插件的Alloc接口函数。

System插件的文档可以参考:中文文档 ,英文文档

其实这两句的意思很简单,就是分配32字节的地址空间并将空间地址保存到寄存器r0。可以想象得到,System::Alloc的返回值是压入到堆栈中的,所以要用Pop指令去将它取出来。至于为什么要分配32个字节呢,下面将会说明。

再看下一句:

System::Call “Kernel32::GetNativeSystemInfo(i) v (r0)”

System::Call是System插件中的一个函数调用接口,看到Kernel32::GetNativeSystemInfo,我们就知道它要调的是Windows API GetNativeSystemInfo。那么就将这个API的声明调出来看看:

void GetNativeSystemInfo( LPSYSTEM_INFO lpSystemInfo );

原来,这个API只有一个参数 — 指向一个名为SYSTEM_INFO结构的指针。这个结构又是怎么样的呢,再看:

[cpp] view plaincopy

  1. typedef struct _SYSTEM_INFO {
  2. union {
  3. DWORD dwOemId;
  4. struct {
  5. WORD wProcessorArchitecture;
  6. WORD wReserved;
  7. };
  8. };
  9. DWORD dwPageSize;
  10. LPVOID lpMinimumApplicationAddress;
  11. LPVOID lpMaximumApplicationAddress;
  12. DWORD_PTR dwActiveProcessorMask;
  13. DWORD dwNumberOfProcessors;
  14. DWORD dwProcessorType;
  15. DWORD dwAllocationGranularity;
  16. WORD wProcessorLevel;
  17. WORD wProcessorRevision;
  18. } SYSTEM_INFO;

这个结构中我们感兴趣的是字段wProcessorArchitecture,这个字段可能有如下几种取值情况:

[cpp] view plaincopy

  1. #define PROCESSOR_ARCHITECTURE_INTEL            0
  2. #define PROCESSOR_ARCHITECTURE_IA64             6
  3. #define PROCESSOR_ARCHITECTURE_AMD64            9
  4. #define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF

好,看看这个调用的后面参数部分:“(i) v (r0)”,这究竟是什么意思呢?

原来,(i)指的是参数类型,v 表示返回值是void类型,r0 表示指针地址。从上面就可以看出 r0 实际上指的是这个结构的地址,这个地址的空间大小是32。

再继续看:

System::Call “*$0(&i2 .r1)”

说NSIS脚本难以理解,主要就是因为它的插件调用参数字符串太难懂了。象这一句,参数就象天书一样。还好,NSIS参考文档网络上有很多,再不济还是有源代码参考的,这就是开源的好处了。

*$0 表示以寄存器0地址空间的结构,&i2 表示是2字节整数,.r1 表示这个2字节整数的值要存放到寄存器1去。

下一句:

System::Free $0

这应该很好理解,就是将寄存器0的地址空间释放掉。

详细解释前面的语句了,后面的应该不难理解。StrCmp $1 9 0 +2 的意思就是看寄存器1的值是否等于PROCESSOR_ARCHITECTURE_AMD64(9),若相等则执行下一句,若不等则执行下下句。这里需要 注意的是,StrCmp不光是指字符串比较,数字比较它也兼任了。

 

免责声明:根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。丨本站为个人博客非盈利性站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途。丨本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权BY-NC-SA协议进行授权

转载请注明:永恒心锁-分享互联网 » NSIS脚本源码分析: 如何判断CPU平台类型

您必须 登录 才能发表评论!