目录

第1章简介    1

第2章版本1.2.3    2

2.1 编译汇编代码    2

2.1.1 32位汇编    2

2.1.2 64位汇编    5

2.2 Visual C++ 6.0    5

2.2.1 编译配置项    6

2.2.2 宏ASMV和ASMINF    6

2.2.3 排除编译    8

2.2.4 自定义编译    8

2.3 Visual C++ 2002    9

2.3.1 编译配置项    10

2.3.2 宏ASMV和ASMINF    11

2.3.3 排除编译    11

2.3.4 嵌入汇编obj文件    11

2.4 Visual C++ 2005    12

2.4.1 编译配置项    12

2.4.2 宏ASMV和ASMINF    13

2.4.3 排除编译    13

2.4.4 嵌入汇编obj文件    13

2.5 宏ZLIB_WINAPI    14

第3章版本1.2.8    15

3.1 编译汇编代码    15

3.1.1 编译    15

3.2 使用Visual C++编译    15

3.2.1 编译前事件    16

第1章简介

zlib是一个用于解压缩的开源C函数库。很多项目(如libpng)会用到它。

它的下载网址如下:

http://sourceforge.net/projects/libpng/files/zlib/

本文对zlib自带的Visual C++项目进行解析。

第2章版本1.2.3

2.1 编译汇编代码

版本1.2.3里,为了提高解压缩效率,函数inflate_fast和longest_match用汇编代码实现了。这两个函数有三个版本,如下表所示:

函数

C

ASM x86

ASM x64

inflate_fast

inffast.c

inffas32.asm

inffas8664.c

inffasx64.asm

longest_match

deflate.c

gvmat32c.c

gvmat32.asm

gvmat64.asm

具体情况为:

函数inflate_fast在inffast.c里有一份实现它的C代码;在inffas32.asm里有一份实现它的32位汇编代码;在inffas8664.c里会调用函数inffas8664fnc,而后者在文件inffasx64.asm里由64位汇编代码实现。

函数longest_match在deflate.c里有一份实现它的C代码;在gvmat32c.c里会调用函数longest_match_7fff和longest_match_686,而这两个函数在文件gvmat32.asm里由32位汇编代码实现;在gvmat64.asm里有一份实现它的64位汇编代码。

简而言之就是:

不用汇编代码,需要编译inffast.c和deflate.c;

使用32位汇编代码,需要编译inffas32.asm、gvmat32c.c、gvmat32.asm;

使用64位汇编代码,需要编译inffas8664.c、inffasx64.asm、gvmat64.asm。

*.c文件在Visual C++编译时会自行处理,*.asm文件就需要特别处理了。

2.1.1 32位汇编

contrib\masmx86目录下的inffas32.asm和gvmat32.asm是32位的汇编代码。编译后可运行在32位的Windows上,也可运行在兼容x86指令的64位Windows上。不能运行在不兼容x86指令的64位Windows上(如:CPU为Itanium的Windows)。

进入contrib\masmx86目录,运行bld_ml32.bat即可编译inffas32.asm和gvmat32.asm。文件bld_ml32.bat的内容如下:

ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm

ml /coff /Zi /c /Flinffas32.lst inffas32.asm

它的含义是调用ml.exe,将gvmat32.asm、inffas32.asm编译生成gvmat32.obj、inffas32.obj。

ml.exe是微软的宏汇编程序,安装了VC++2002至VC++2015后ml.exe也同时被安装,它所在的目录如下表所示:

vc版本

目录

其它

2002

C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin

 

2003

C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin

 

2005

C:\Program Files\Microsoft Visual Studio 8\VC\bin

amd64\ml64.exe

x86_amd64\ml64.exe

2008

C:\Program Files\Microsoft Visual Studio 9.0\VC\bin

amd64\ml64.exe

x86_amd64\ml64.exe

2010

C:\Program Files\Microsoft Visual Studio 10.0\VC\bin

amd64\ml64.exe

x86_amd64\ml64.exe

2012

C:\Program Files\Microsoft Visual Studio 11.0\VC\bin

amd64\ml64.exe

x86_amd64\ml64.exe

2013

C:\Program Files\Microsoft Visual Studio 12.0\VC\bin

amd64_x86\ml.exe

amd64\ml64.exe

x86_amd64\ml64.exe

2015

C:\Program Files\Microsoft Visual Studio 14.0\VC\bin

amd64_x86\ml.exe

amd64\ml64.exe

x86_amd64\ml64.exe

说明:

1、从vc2005开始提供了ml64.exe,它用来编译生成64位的汇编代码;

2、从vc2013开始又提供了amd64_x86\ml.exe;

3、两个ml.exe和两个ml64.exe的区别:

ml.exe                是32位程序,编译生成32位的汇编代码;

amd64_x86\ml.exe        是64位程序,编译生成32位的汇编代码;

amd64\ml64.exe            是64位程序,编译生成64位的汇编代码;

x86_amd64\ml64.exe    是32位程序,编译生成64位的汇编代码。

上述文件夹命名都是有含义的:amd64_x86前面的amd64表示ml.exe是64位的,后面的x86表示编译生成的汇编代码是32位的;amd64表示amd64_amd64,即ml.exe和生成的汇编代码都是64位的。

为了能够正常编译,有两种方法:

方法一:将ml.exe从相应的目录中复制到bld_ml32.bat所在目录,运行bld_ml32.bat即可;

方法二:在bld_ml32.bat所在目录创建vc2002.bat,其内容如下:

%VSCOMNTOOLS%\..\..\Vc7\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm

%VSCOMNTOOLS%\..\..\Vc7\bin\ml /coff /Zi /c /Flinffas32.lst inffas32.asm

现在运行vc2002.bat即可调用C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin\ml.exe进行编译。

VSCOMNTOOLS是一个环境变量,安装vc2002后它被自动添加到系统里,如下图所示:

同理,还可以创建vc2003.bat

"%VS71COMNTOOLS%..\..\Vc7\bin\ml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm

"%VS71COMNTOOLS%..\..\Vc7\bin\ml" /coff /Zi /c /Flinffas32.lst inffas32.asm

还可以创建vc2005.bat

"%VS80COMNTOOLS%..\..\VC\bin\ml" /coff /Zi /c /Flgvmat32.lst gvmat32.asm

"%VS80COMNTOOLS%..\..\VC\bin\ml" /coff /Zi /c /Flinffas32.lst inffas32.asm

经实际测试,vc2002.bat和vc2003.bat能够正常运行,而vc2005.bat在编译时出错。也就是说ml.exe只能使用vc2002和vc2003附带的版本,再高的版本就不行了。

2.1.2 64位汇编

contrib\masmx64目录下的gvmat64.asm和inffasx64.asm是64位的汇编代码。编译后可运行在64位的Windows上(CPU为Itanium的Windows例外)。

进入contrib\masmx64目录,运行bld_ml64.bat即可编译gvmat64.asm和inffasx64.asm。文件bld_ml64.bat的内容如下:

ml64.exe /Flinffasx64 /c /Zi inffasx64.asm

ml64.exe /Flgvmat64 /c /Zi gvmat64.asm

它的含义是调用ml64.exe,将gvmat64.asm、inffasx64.asm编译生成gvmat64.obj、inffasx64.obj。

为了能够正常编译,有两种方法:

方法一:将ml64.exe从C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64复制到bld_ml64.bat所在目录,运行bld_ml64.bat即可;

方法二:在bld_ml64.bat所在目录创建vc2005.bat,其内容如下:

"%VS80COMNTOOLS%..\..\VC\bin\x86_amd64\ml64.exe" /Flinffasx64 /c /Zi inffasx64.asm

"%VS80COMNTOOLS%..\..\VC\bin\x86_amd64\ml64.exe" /Flgvmat64 /c /Zi gvmat64.asm

现在运行vc2005.bat即可进行编译。

2.2 Visual C++ 6.0

使用Visual C++6.0打开projects\visualc6\zlib.dsw,如下图所示。可以看到一共有三个项目:example、minigzip、zlib。前两个项目不用理会,鼠标右键单击zlib,然后单击【Set as Active Project】,设置zlib为活动项目。

2.2.1 编译配置项

项目zlib一共有8个编译配置项,如下图所示:

"Win32 DLL*"表示编译生成动态库;

"Win32 LIB*"表示编译生成静态库;

"*Release"表示编译生成Release版,发布程序时使用此版本;

"*Debug"表示编译生成Debug版,调试程序时使用此版本;

含有ASM的表示编译时使用汇编代码;

未含ASM的表示编译时不使用汇编代码。

2.2.2 宏ASMV和ASMINF

查看zlib的配置,当选中含有ASM的编译配置项时,可以看到宏ASMV和ASMINF被定义了。如下图所示:

宏ASMINF被定义,则inflate_fast的C代码被禁用,以下代码节选自inffast.c

#ifndef ASMINF

void inflate_fast(strm, start)

z_streamp strm;

unsigned start;

{

... ... ...

}

#endif /* !ASMINF */

宏ASMV被定义,则longest_match的C代码被禁用,以下代码节选自deflate.c

#ifndef ASMV

local uInt longest_match(s, cur_match)

deflate_state *s;

IPos cur_match;

{

... ... ...

}

#endif /* ASMV */

也就是说:定义宏ASMINF的含义是启用inflate_fast的汇编代码;定义宏ASMV的含义是启用longest_match的汇编代码。

2.2.3 排除编译

Visual C++6.0无法编译64位的汇编代码,因此不用管inffas8664.c、inffasx64.asm、gvmat64.asm这三个文件。

zlib项目里含有与32位汇编相关的三个文件:gvmat32.asm、gvmat32c.c、inffas32.asm。

当选中不含ASM的编译配置项时,可以看到这三个文件在编译时是被排除在外的,如下图所示:

当选中含有ASM的编译配置项时,可以看到这三个文件将参与编译,如下图所示:

2.2.4 自定义编译

当选中含有ASM的编译配置项时,可以看到gvmat32.asm、inffas32.asm是如何被编译的。如下图所示:

命令如下所示:

ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"

因为VC++6.0并不自带ml.exe,因此上述命令执行时将会失败。解决方法:将C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\ml.exe复制到C:\Program Files\Microsoft Visual Studio\VC98\Bin。即将vc2002的ml.exe复制到vc6的安装目录。

2.3 Visual C++ 2002

使用vc2002打开contrib\vstudio\vc7\zlibvc.sln,如下图所示。可以看到一共有五个项目:miniunz、minizip、testZlibDll、zlibstat、zlibvc。前三个项目不用理会,zlibstat、zlibvc分别是zlib的静态库、动态库项目。这里只关心zlibvc项目,鼠标右键单击zlibvc,然后单击【Set as StartUp Project】,设置zlibvc为活动项目。

2.3.1 编译配置项

项目zlib一共有5个编译配置项,如下图所示:

"Debug"编译生成Debug版,调试程序时使用此版本;

"Release"编译生成Release版,使用汇编代码;

"ReleaseAxp"编译生成Release版,不使用汇编代码;

"ReleaseWithoutAsm"编译生成Release版,不使用汇编代码。它似乎与ReleaseAxp没什么区别;

"ReleaseWithoutCrtdll"编译生成Release版,使用汇编代码。

Release、ReleaseAxp、ReleaseWithoutAsm使用的C运行时库文件不是msvcr70.dll,而是crtdll.dll。笔者对此的理解是:crtdll.dll比msvcr70.dll更加普及。

ReleaseWithoutCrtdll使用的C运行时库文件是msvcr70.dll不再是crtdll.dll。

虽然crtdll.dll比msvcr70.dll更加普及,但是crtdll.lib很难找到了。没有crtdll.lib的情况下,Release、ReleaseAxp、ReleaseWithoutAsm无法完成链接。

2.3.2 宏ASMV和ASMINF

使用汇编代码的配置项,均定义了宏ASMV和ASMINF,如下图所示

2.3.3 排除编译

使用汇编代码的配置项,gvmat32c.c被排除编译。如下图所示:

未使用汇编代码的配置项,gvmat32c.c未被排除编译。如下图所示:

2.3.4 嵌入汇编obj文件

与VC++6.0不同,VC2002里不再自定义编译asm文件,而是直接使用asm文件编译后的obj文件。

下图是配置项"ReleaseWithoutCrtdll"的Linker、Input选项。可以看到它将使用asm文件的编译结果文件:gvmat32.obj、inffas32.obj。

2.4 Visual C++ 2005

使用vc2005打开contrib\vstudio\vc8\zlibvc.sln,如下图所示。可以看到一共有六个项目。前四个项目不用理会,zlibstat、zlibvc分别是zlib的静态库、动态库项目。这里只关心zlibvc项目,鼠标右键单击zlibvc,然后单击【Set as StartUp Project】,设置zlibvc为活动项目。

2.4.1 编译配置项

项目zlib一共有3个编译平台,如下图所示:

Win32 编译出32位程序,可运行在32位和64位Windows上;

x64 编译出64位程序,可运行在64位Windows上;

Itanium编译出64位程序,只能运行在CPU为Itanium的Windows上。

每个编译平台又有3个配置项,如下图所示:

"Debug"编译生成Debug版,调试程序时使用此版本;

"Release"编译生成Release版,使用汇编代码;

"ReleaseWithoutAsm"编译生成Release版,不使用汇编代码。

2.4.2 宏ASMV和ASMINF

使用汇编代码的配置项,均定义了宏ASMV和ASMINF,如下图所示

2.4.3 排除编译

gvmat32c.c和inffas8664.c可能被排除编译。如下图所示:

编译平台为Win32时,inffas8664.c始终被排除编译,gvmat32c.c视是否使用汇编代码而定;

编译平台为x64时,gvmat32c.c始终被排除编译,inffas8664.c视是否使用汇编代码而定;

编译平台为Itanium时,gvmat32c.c和inffas8664.c始终被排除编译。因为这个编译平台的汇编代码压根没有实现。

2.4.4 嵌入汇编obj文件

与VC2002相同,VC2005也不再自定义编译asm文件,而是直接使用asm文件编译后的obj文件。

需要注意的是:Win32和x64平台使用的obj文件是不同的。下图是x64平台下,使用masmx64目录下的两个obj文件。

2.5 宏ZLIB_WINAPI

定义了ZLIB_WINAPI,则zlib导出的函数其调用约定全部被设置为WINAPI,即__stdcall。这么做的好处是:不是C语言的客户程序,如VB6.0也可以使用zlib动态库了。

VC++6.0的宏定义里没有发现ZLIB_WINAPI,也就是说VC++6.0编译生成的zlib动态库,其导出函数的调用约定不是__stdcall,而是__cdecl。

VC2002和VC2005的宏定义里均有ZLIB_WINAPI,编译生成zlib动态库后,其导出函数的调用约定是__stdcall。

客户端使用zlib动态库时,应该也要定义ZLIB_WINAPI,具体代码如下:

#define ZLIB_WINAPI

#include "zlib.h"

遗憾的是,至少在libpng1.4.12项目里笔者并没有发现#include "zlib.h"之前有#define ZLIB_WINAPI。

笔者认为比较好的方法应该是把#define ZLIB_WINAPI直接添加到zlib.h里,保证编译生成zlib动态库、客户端调用zlib时zlib的导出函数均是__stdcall的。

第3章版本1.2.8

3.1 编译汇编代码

与版本1.2.3相比,版本1.2.8的longest_match函数的32位汇编代码由gvmat32c.c、gvmat32.asm两个文件合并为match686.asm这一个文件。具体如下表所示:

函数

C

ASM x86

ASM x64

inflate_fast

inffast.c

inffas32.asm

inffas8664.c

inffasx64.asm

longest_match

deflate.c

match686.asm

gvmat64.asm

现在的情况变为:

不用汇编代码,需要编译inffast.c和deflate.c;

使用32位汇编代码,需要编译inffas32.asm、match686.asm;

使用64位汇编代码,需要编译inffas8664.c、inffasx64.asm、gvmat64.asm。

3.1.1 编译

编译32位汇编代码:将ml.exe从C:\Program Files\Microsoft Visual Studio 8\VC\bin\复制到contrib\masmx86,运行bld_ml32.bat即可。

编译64位汇编代码:将ml64.exe从C:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64复制到contrib\masmx64,运行bld_ml64.bat即可。

当然,使用vc2008、vc2010、vc2012、vc2013、vc2015的ml.exe、ml64.exe应该也是可以的。

3.2 使用Visual C++编译

进入contrib\vstudio目录,可以发现vc9、vc10、vc11三个子目录,分别用vc2008、vc2010、vc2012编译。设置与上一章大致相同,这里就不赘述了。需要特别说明的是vc2010里的"编译前事件"。

3.2.1 编译前事件

vc2010里有"编译前事件",如下图所示:

其含义为:编译代码之前将执行"编译前事件",上图的命令如下所示:

cd ..\..\masmx64

bld_ml64.bat

其含义就是设置contrib\masmx64为当前目录,然后执行bld_ml64.bat。

..\..\masmx64是相对路径,相对于项目文件(contrib\vstudio\vc10\zlibvc.vcxproj)的相对路径,即contrib\vstudio\vc10\..\..\masmx64,也就是contrib\masmx64。

使用vc2010编译zlib代码,不用费劲找ml.exe和ml64.exe了,也不用考虑应该使用哪个版本的ml.exe和ml64.exe了。一切方便了很多。

VC++编译zlib的更多相关文章

  1. vc编译 zlib 1.2.8

    最近用到gzip关的算法,于是想起了zlib这个库,于是将其下载下来编译. 首先,在官网上下载源码包:http://zlib.net/zlib-1.2.8.tar.gz 解压之后,打开vc 命令工具: ...

  2. VC++编译libpng

    目录 第1章简介    1 第2章 Visual C++6.0    2 2.1 打开项目    2 2.2 编译宏    3 2.2.1 小结    5 第3章 Visual C++2010     ...

  3. windows下使用cmake编译zlib与libpng libjpeg

    win7下使用VS2010编译jpeglib 1.下载源代码下载地址:http://www.ijg.org/files/,     选择最新版本的windows版本压缩包,进行下载.     jpeg ...

  4. 用VC编译lua源码,生成lua语言的解释器和编译器

    用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编 ...

  5. VC++编译MPIR 2.7.0

    目录 第1章编译    2 1.1 简介    2 1.2 下载    3 1.3 解决方案    4 1.4 创建项目    5 1.5 复制文件树    6 1.6 不使用预编译头文件    8 ...

  6. VC++编译GSL

    目录 第1章 VC++    1 1.1 修改行结束符    1 1.2 修改#include "*.c" 为 #include "*.inl"    2 1. ...

  7. 让VC编译出来的程序不依赖于msvcr80.dll/msvcr90.dll/msvcr100.dll等文件

    ---转载:http://hi.baidu.com/liu_haitao/item/e2157ac3a3c32a0bc610b253 让VC编译出来的程序不依赖于msvcr80.dll/msvcr90 ...

  8. 【Python学习】由于windows环境问题导致的不能安装某些需要VC编译的插件

    由于windows环境问题导致的不能安装某些需要VC编译的插件 下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 安装方法: 在CMD中输入 pip in ...

  9. VC编译连接选项详解

    VC编译连接选项详解 大家可能一直在用VC开发软件,但是对于这个编译器却未必很了解.原因是多方面的.大多数情况下,我们只停留在“使用”它,而不会想去“了解”它.因为它只是一个工具,我们宁可把更多的精力 ...

随机推荐

  1. JAVAWeb使用POI做导出Excel

    一.需要了解的API ①HSSFWorkBook //代表一个Excel文件 ②HSSFSheet //代表一个表 ③HSSFRow //代表一个表中的某一行 ④HSSFCell //代表一个表中的某 ...

  2. IOSView翻转扭矩位移

    CoreGraphics.h CGAffineTransform rotation = CGAffineTransformMakeRotation(M_PI_2);[xxx setTransform: ...

  3. easyUI学习网站

    http://www.runoob.com/jeasyui/plugins-form-timespinner.html http://www.jeasyui.net/plugins/178.html ...

  4. SaveXml的方法汇总

    /// <summary> /// 保存XML文件 /// </summary> /// <returns></returns> public bool ...

  5. #使用while循环输入1 2 3 4 5 6 8 9 10

    #!/usr/bin/env python #使用while循环输入1 2 3 4 5 6 8 9 10 import time start = 1 while True: if start == 7 ...

  6. CodeForces 454C Little Pony and Expected Maximum

    Little Pony and Expected Maximum Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I6 ...

  7. SetWindowHookEx 做消息响应

    HHOOK g_Hook = NULL; LRESULT CALLBACK CallWndProc( _In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM l ...

  8. 搭建本地的git仓库

    折腾了快一天了,终于搭建成功了. 分享一下搭建的步骤: 一.GIT仓库的创建 1. adduser git 2. passwd git 此例设置git的密码为123456 3. cd /home/gi ...

  9. 【原创】pads layout 画多边形copper,出现Self-Intersecting Polygon,解决办法

    在做线性位移传感器的电路板时,需要在一个很小的多边形Copper操作,总是提示“Self-Intersecting Polygon”报错,意思是outline线自身交叉,换句话说就是线宽与多边形尺寸没 ...

  10. CG绘画笔记

    看一些比较好的作品:看作品哪些部分,部件,盔甲比较吸引人,提取一个比较好的点,进行组合创作. 逆光.切光布局构图 创作:故事.情感.经历.朋友.时代 灵感: 电影.音乐 变化(色彩)透视 空气透视视觉 ...