??xml version="1.0" encoding="utf-8" standalone="yes"?> Memset 用来对一D内存空间全部设|ؓ某个字符Q一般用在对定义的字W串q行初始化ؓ‘ ’?/span>‘\ 主要应用是初始化某个内存I间 memset可以方便的清IZ个结构类型的变量或数l?/span> 如: struct sample_struct 对于变量 一般情况下Q清I?/span>stTest的方法: stTest.csName[0]='\0'; ?/span>memset非常方便: 如果是数l: struct sample_struct TEST[10]; memcpy 用来做内存拷贝,你可以拿它拷贝Q何数据类型的对象Q可以指定拷贝的数据长度?br> memcpy是用?/span>copy源空间的数据到目的空间中 Strcpy 只能拷贝字W串了,它遇?/span>'\0'q束拷贝?/span> 例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a)Q要注意a中的字符串长度(W一?/span>‘\
*vector list deque Qvector是一U可以默认用的序列cdQ当很频J的对序列中q行插入和删除的时候应该用listQ大部分发生在尾部的话用dequeq种数据l构
*q箋内存容器和基于节点的容器的区?br />q箋容器vector/string/deque在一个或者多个内存块中保存它们的元素Q如果新元素被插入或者已存元素被删除Q其他在同一个内存块中的元素必须向上或者向下移动来为新元素提供I间或者填充原来被删除的元素所占的I间Q这U移动媄响了效率?br />Z节点的listQ插入或者删除的时候不需要移?br />*序列容器在Q意位|插入一个新元素Q关联容器不可以
*容器中的数据的内存布局需要兼容C吗,如果是,那只能用vector
*查找速度Q散列容器》排序的vector>标准的关联容?br />*需要可靠的插入和删除的能力Q如果是需要用基于节点的容器
*需要P代器、指针、引用的实效ơ数减少到最,如果是,使用介于节点的容器,一般来_在连l容器上的插入和删除会所有指向容器的q代器指针和引用实效
]]>
http://blog.csdn.net/lychee007/archive/2009/05/31/4227419.aspx
http://social.microsoft.com/Forums/es-ES/visualcpluszhchs/thread/ff6ddac2-a69d-4c02-ad20-d73cb4335c24
http://hi.baidu.com/237rxd/blog/item/35a51efa18e098859e5146b9.html
http://topic.csdn.net/t/20050712/20/4140158.html
]]>
?/span>:char a[100];memset(a, '\0', sizeof(a));
{
char csName[16];
int iSeq;
int iType;
};
struct sample_strcut stTest;
stTest.iSeq=0;
stTest.iType=0;
memset(&stTest,0,sizeof(struct sample_struct));
?/span>
memset(TEST,0,sizeof(struct sample_struct)*10);
例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a)Q会造成b的内存地址溢出?br>
strcpy用于字符?/span>copy,遇到‘\
]]>
]]>wchar_t* atow(char* src)
{
int dest_len;
dest_len = MultiByteToWideChar(CP_ACP,0,src,-1,NULL,0);
wchar_t *dest = new wchar_t[dest_len];
if(dest == NULL)
return NULL;
MultiByteToWideChar(CP_ACP,0,src,-1,dest,dest_len);
return dest;
}
]]>
1Q神马是Dll和LibQ神马是静态链接和动态链?/p>
大家都懂的,DLL是动态链接库QLIB是静态链接库。DLL其实是EXEQ只不过没main?/p>
动态链接是相对于静态链接而言的。所谓静态链接就是把函数或过E直接链接到可执行文件中Q成为可执行E序中的一部分Q当多个E序调用同样的函数时Q内存里׃有这个函数的多个拯Q浪费内存资源。而动态链接则是提供了一个函数的描述信息l可执行文gQƈ没有内存拯Q,当程序被夹在到内存里开始运行的时候,pȝ会在底层创徏DLL和应用程序之间的q接关系Q当执行期间需要调用DLL函数Ӟpȝ才会真正Ҏ链接的定位信息去执行DLL中的函数代码?/p>
在WINDOWS32pȝ底下Q每个进E有自己?2位的U性地址I间Q若一个DLL被进E用,则该DLL首先会被调入WIN32pȝ的全局堆栈Q然后通过内存映射文g方式映射到这个DLL的进E地址I间。若一个DLL被多个进E调用,则每个进E都会接收到该DLL的一个映像,而非多䆾的拷贝。但Q在WIN16pȝ下,每个q程需要拥有自q一份DLLI间Q可以理解ؓ何静态链接没啥区别?/p>
2QDLL和LIB区别和联pR?/p>
DLL是程序在q行阶段才需要的文g?/p>
LIB是程序编译时需要链接的文g?/p>
DLL只有一U,其中一定是函数和过E的实现?/p>
LIB是有两种。若只生成LIB的话Q则q个LIB是静态编译出来的Q它内部包含了函数烦引以及实玎ͼq个LIB会比较大。若生成DLL的话Q则也会生成一个LIBQ这个LIB和刚才那个LIB不同Q它是只有函数烦引,没有实现的,它很。但是这俩LIB依然遵@上个原则Q是在编译时候是需要被链接的。若不链接第一个LIB的话Q在E序q行时会无法扑ֈ函数实现Q当掉。若不链接第二个LIB的话Q在E序q行时依然会无法扑ֈ函数实现。但W二ULIB有一U替代方式,是在程序里Q用LoadLibrary,GetProcAddress替代W二个LIB的功能。第一ULIB生成的EXE文g会很大,因ؓLIB所有信息被静态链接进EXE里了。第二种LIB生成的EXE文g会比较小Q因为函数过E实C旧在DLL内?/p>
Q啰嗦了一堆,某志希望大家能够明白两个LIB的区别。要再不行的话,我们可以静态编译的LIBUCؓ 静态链接库。但动态编译的LIBUCؓ 引入库。可能会比较好一些。)
静态链接LIB的优Ҏ免除挂接动态链接库Q缺ҎEXE大,版本控制ȝ些?/p>
动态链接DLL的优Ҏ文g,版本更换时换DLL好了,~点是多了点文g。动态链接若是被多个q程使用Q会更加方便和节省内存?/p>
3Qؓ什么编译DLL时M同时生成一个LIBQ这个LIB有用吗?
若我们不是用静态链接,而用DLLQ那么我们也需要一个LIBQ这个LIB的作用是被链接到E序里,在程序运行时告诉pȝ你需要什么DLL文g。这个LIB里保存的是DLL的名字和输出函数入口的顺序表。它是有意义的?/p>
当然Q若我们的应用程序里不链接这个LIBQ则可以使用LoadLibrary,GetProcAddress来告诉系l我们在q行旉要怎么着DLL以及其内的函数?/p>
4QDLL意义?/p>
1QDLL真正实现了跨语言。各U语a都可以生成DLLQ而对pȝ以及应用E序来说Q哪U语a生成的DLL是没有区别的?/p>
2QDLL有够的装性,对于版本更新有很大好处。因为DLL是运行期间才会用,所以,即DLL内函数实现有变化Q只要参数和q回g发生变化Q,E序是不需要进行编译的。大大提高了软g开发和l护的效率?/p>
3QDLL被多个进E用,因ؓ有内存映机Ӟ无需占用更多内存?/p>
5Q创建DLL。(注意Q某志就不再讲解使用MFC AppWizard[dll] 方式创徏DLL了。有兴趣的自己去癑ֺ。这里创建DLL只指使用Win32 Dynamic-link Library创徏Non-MFC DLL。呃QDLL的三U类型就不解释了Q依旧那句话Q百度一下你q道。)
每个应用E序必须有一个main或者winmain函数作ؓ入口QDLL一P有自q~省的入口函敎ͼ是DllMain。函数如?/p>
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID
lpReserved)
{
switch (ul_reason_for_call)
{
case
DLL_PROCESS_ATTACH: // q程被调?br> case DLL_THREAD_ATTACH: // U程被调?br> case
DLL_THREAD_DETACH: // U程被停?br> case DLL_PROCESS_DETACH:
// q程被停?br> break;
}
return TRUE;
}
一般情况下Q我们不需要对q个~省的入口函数进行什么修改,它就会动态链接库得到正确的初始化。但是,当我们的DLL需要额外分配内存或者资源的时候,或者,DLL希望对调用自qq程或线E进行初始化或清除的额外操作Ӟ可以在上qC码case中加一些自己感冒的东东。(?#8230;…不想l写? -OrzQ现在是晚上2点了Q明天还一堆的事情Q?/p>
DLL对于导出cd导出函数没啥不同。只要加?__declspec( dllexport ) 修饰函数或者类好了?/p>
但是有查看过DLL代码的h员都会经常见到这么一D代?/p>
#ifdef FK_DLL_EXPORTS
#define FK_DLL __declspec( dllexport )
#else
#define FK_DLL __declspec( dllimport )
#endif
意义很明显,但是Q问题是 FK_DLL_EXPORTS q个宏是应该在哪儿定义呢Q在DLL目内,q是在用DLL的应用程序内Q?/p>
q点某志曾迷p很久,呵呵~其实后来xQ还是蛮明确的。export是导出。import是导入。对于DLL来说Q是要导些函数给其他应用E序使用的,所以应当定? FK_DLL_EXPORTS 宏。对于用DLL的应用程序来_是导入,是无需定义的?/p>
使用时候也很简单?/p>
class FK_DLL CMyDllClass{} ;
则整个类被导出?/p>
FK_DLL void MyTestFun( int a );
则该函数被导出?/p>
但是有时我们可以见到q样的代?/p>
extern "C" FK_DLL void MyTestFun2( float b );
其中extern "C"的原理就是标C函数要求以C形式去进行编译,不要以C++形式ȝ译。具体的~译原理׃|嗦了,而言之,被extern "C"定义函数Q可以被C以及其他语言q行DLL调用Q而未被extern "C"定义的函敎ͼC是无法访问DLL中这个函数的?/p>
在VS中开发DLLq有一U方式,使用.def文g?/p>
新徏个文本文档,改后~为FKDll.defQ加入到工程里?/p>
FKDll.def里加入以下代?/p>
LIBRARY FKDll
EXPORTS
可以了。其中,LIBRARY语句是说?def文g是属于FKDllq个Dll的。EXPORTS下面是我们需要导出的函数名。后面加的@+数字Q是表示导出函数的顺序编受这样就_了。(详细的自q度,好困QzzzZZZQ?/p>
6Q用DLL
使用DLL有两U方式。显式链接和隐式链接?/p>
隐式链接很容易。直?progam comment(lib, "FKDll.lib") 可以。当Ӟ也可以在目工程->属?>链接库里加上库和路径Q相对\径和l对路径都可以)?/p>
昑ּ链接则麻烦些。在E序中用LoadLibrary加蝲DLLQ再GetProcAddress获取函数实现Q在E序退Z前,调用FreeLibrary来动态释放掉链接库?/p>
例如Q?/p>
void Main()
{
typedef void (*FKDllFun1)(int a);
FKDllFun1 pFun1;
HINSTANCE hDLL = LoadLibrary("FKDll.dll"); // 若hDll为空则读取Dllp|?/p>
pFun1 = (pFun1)GetProcAddress(hDll, "MyTestFun1" ); // 从应用程序中的DLL镜像中获取名?MyTestFun1 的函数指?/p>
pFun1( 100 );
FreeLibrary(hDll);
}
当然Q我们刚?def里面q指定了导出函数的导出顺序,那么我们可以修改里面获取函数指针那一Dؓ
pFun1 = (pFun1)GetProcAddress(hDll, MAKEINTERSOURCE(1) ); // 1 是刚才指定的MyTestFun1函数导出序~号?/p>
q样可以更快Q但是别编可混了Q会D诡异的错误?/p>
7Q比较显式链接和隐式链接?/p>
可能的话Q尽量用显式链接?/p>
昑ּ链接可以在程序执行时动态的加蝲DLL和卸载DLL文gQ隐式链接是做不到的?/p>
昑ּ链接LoadLibraryQGetProcAddress时能L是否加蝲p|Q我们可以对其进行检查错误处理。而显式链接可能是一个很恶劣的提C或是程序崩溃的l果?/p>
对于有些Excd的加强函敎ͼ昑ּ链接可以允许我们扑ֈ替代Ҏ。也包括选择D3d9.dll和OpenGL.dll时也可采用同样处理?/p>
例如Q?/p>
if( GetProcAddress( hDll, "FKDllFunEx") == NULL )
{
pFun = GetProcAddress( hDll, "FKDllFun"); // 然后使用pFunq行处理
}
8Q导出类和导出函?/p>
cd函数的导出方式上面给Z说明Q原本极其类似的?/p>
我们说下使用导出cR?/p>
若我们隐式的使用了一个导出类Q则我们在应用程序里l承它的时候,如同该cd在应用程序代码里一P无需M处理?/p>
例如Q?/p>
class FK_DLL CMyDllClass{} ; // Dll文g内的代码
-----------------------
class CAppClass : public CMyDllClass // 应用E序内代码,无需做Q何处理?/p>
{
....
}
也可以直接用DLL导出c?/p>
void main
{
CMyDllClass* pClass = new CMyDllClass ();
}
但是Q若应用E序声明或者分cM个DLL中导出类的对象时会存在一个很讨厌的问题:q个操作会内存跟踪pȝ失效Q光误的报告内存分配和释放情c?/p>
册个问题,我们可以l出两个接口函数对DLL导出c进行创建销毁支持,可以内存跟踪pȝ正常了。例?/p>
class FK_DLL CMyDllClass{} ;
额外增加俩函?/p>
FK_DLL CMyDllClass* CreateMyDllClass(){ return new CMyDllClass(); }
FK_DLL void DestoryMyDllClass( CMyDllClass* p_pClass ){ delete p_pClass; }
-----------------------------------------------
上面的方法可以正进行内存跟t了Q但是,因ؓDLL导出cCMyDllClass依旧是导出的状态,用户同样可以跌我们提供的接口直接用。那么怎么办呢。方法是不再对类q行DLL导出Q而对cd的函数全部进行DLL导出卛_Q?/p>
-----------------------------------------------
但是若仅仅提供上面两个接口函C及类内全部函敎ͼ的确功能可以实现Q却无法q行cȝ承了。若q个cȝ承很重要Q必d放,那么需要用新的内存跟t程序替换应用程序内的原有内存跟t程序。或者用下面的一个方法。(见模?Q复杂问题)
-----------------------------------------------
同样Q我们也可以发现Q在不导出DLLcLw,而只导出DLLcd函数也有一些好处,一些我们不希望外界知道的函数可以不讄导出标记Q这q一步保护了DLL内函数的安全性?/p>
9Q复杂问题?/p>
若我们用LoadLibrary昑ּ加蝲一个DLLQƈ试在应用程序中调用一个类内成员函数的话,无论该函数是否在头文件中有声明,VS会给Z?unresolved external symbolQ未解析的外部符P"的错误。我们此时可以将目属性中的内联函数扩展选项修改?Only __inline"?Any Suitable"卛_。但Q我们可能在调试q编的时候期望关闭内联函数扩展,那么另一U解x案是Q将希望导出的函数声明ؓ虚函敎ͼ例如
class CMyDllClass
{
FK_DLL virtual void MyTestFun( int a ){ dosth(); }
// 用上面代码替?FK_DLL void MyTestFun( int a ){ dosth(); }
}
q样做还有一个额外的好处。将导出的类成员函数讄函数之后Q该虚函数所在的cd应用E序中也如同被声明一P可以接受l承?/p>
例如若是上面的做法,应用E序可以进行顺利承,而不必要求CMyDllClass 被标CZؓ导出。(原理不知Q希望精通底层的高手协助解释。)
class CAppClass : public CMyDllClass // 应用E序内代码,无需做Q何处理?/p>
{
....
}
见到q两个符L很多不同的用法,整理在一?/font>
宏中"#"?/span>"##"的用?/span>
一、一般用?/span>
我们使用#把宏参数变ؓ一个字W串,?/span>##把两个宏参数贴合在一?/span>.
用法:
#include<cstdio>
#include<climits>
using namespace std;
#define STR(s) #s
#define CONS(a,b) int(a##e##b)
int main()
{
printf(STR(vck)); // 输出字符?/span>"vck"
printf("%d\n", CONS(2,3)); // 2e3 输出:2000
return 0;
}
二、当宏参数是另一个宏的时?/span>
需要注意的是凡宏定义里有用'#'?/span>'##'的地方宏参数是不会再展开.
1, ?/span>'#'?/span>'##'的情?/span>
#define TOW (2)
#define MUL(a,b) (a*b)
printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));
q行的宏会被展开为:
printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
MUL里的参数TOW会被展开?/span>(2).
2, 当有'#'?/span>'##'的时?/span>
#define A (2)
#define STR(s) #s
#define CONS(a,b) int(a##e##b)
printf("int max: %s\n", STR(INT_MAX)); // INT_MAX #include<climits>
q行会被展开为:
printf("int max: %s\n", "INT_MAX");
printf("%s\n", CONS(A, A)); // compile error
q一行则是:
printf("%s\n", int(AeA));
A不会再被展开, 然而解册个问题的Ҏ很简?/span>. 加多一层中间{换宏.
加这层宏的用意是把所有宏的参数在q层里全部展开, 那么在{换宏里的那一个宏(_STR)p得到正确的宏参数.
#define A (2)
#define _STR(s) #s
#define STR(s) _STR(s) // 转换?/span>
#define _CONS(a,b) int(a##e##b)
#define CONS(a,b) _CONS(a,b) // 转换?/span>
printf("int max: %s\n", STR(INT_MAX)); // INT_MAX,int型的最大|Z个变?/span> #include<climits>
输出?/span>: int max: 0x7fffffff
STR(INT_MAX) --> _STR(0x7fffffff) 然后再{换成字符Ԍ
printf("%d\n", CONS(A, A));
输出为:200
CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))
三?/span>'#'?/span>'##'的一些应用特?/span>
1、合q匿名变量名
#define ___ANONYMOUS1(type, var, line) type var##line
#define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
#define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
例:ANONYMOUS(static int); ?/span>: static int _anonymous70; 70表示该行行号Q?/span>
W一层:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
W二层: --> ___ANONYMOUS1(static int, _anonymous, 70);
W三层: --> static int _anonymous70;
xơ只能解开当前层的宏,所?/span>__LINE__在第二层才能被解开Q?/span>
2、填充结?/span>
#define FILL(a) {a, #a}
enum IDD{OPEN, CLOSE};
typedef struct MSG{
IDD id;
const char * msg;
}MSG;
MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
相当于:
MSG _msg[] = {{OPEN, "OPEN"},
{CLOSE, "CLOSE"}};
3、记录文件名
#define _GET_FILE_NAME(f) #f
#define GET_FILE_NAME(f) _GET_FILE_NAME(f)
static char FILE_NAME[] = GET_FILE_NAME(__FILE__);
4、得C个数值类型所对应的字W串~冲大小
#define _TYPE_BUF_SIZE(type) sizeof #type
#define TYPE_BUF_SIZE(type) _TYPE_BUF_SIZE(type)
char buf[TYPE_BUF_SIZE(INT_MAX)];
--> char buf[_TYPE_BUF_SIZE(0x7fffffff)];
--> char buf[sizeof "0x7fffffff"];
q里相当于:
char buf[11];
一、常用指?/span>
1. 通用数据传送指?/span>.
MOV 传送字或字?/span>.
MOVSX 先符h?/span>,再传?/span>.
MOVZX 先零扩展,再传?/span>.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA ?/span>AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA ?/span>DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD ?/span>EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD ?/span>EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的序
XCHG 交换字或字节.( 臛_有一个操作数为寄存器,D寄存器不可作ؓ操作?/span>)
CMPXCHG 比较q交换操作数.( W二个操作数必须为篏加器AL/AX/EAX )
XADD 先交换再累加.( l果在第一个操作数?/span> )
XLAT 字节查表转换.
BX 指向一?/span> 256 字节的表的v?/span>, AL 的烦引?/span> (0-255,?/span> 0-FFH); q回 AL 为查表结?/span>. ( [BX+AL]->
2. 输入输出端口传送指?/span>.
IN I/O端口输入. ( 语法: IN 累加?/span>, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加?/span> )
输入输出端口qx式指定时, 其范围是 0-255; 由寄存器 DX 指定?/span>,其范围是 0-65535.
3. 目的地址传送指?/span>.
LEA 装入有效地址.
?/span>: LEA DX,string ;把偏Ud址存到DX.
LDS 传送目标指?/span>,把指针内容装?/span>DS.
?/span>: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指?/span>,把指针内容装?/span>ES.
?/span>: LES DI,string ;把段地址:偏移地址存到ESDI.
LFS 传送目标指?/span>,把指针内容装?/span>FS.
?/span>: LFS DI,string ;把段地址:偏移地址存到FSD.
LGS 传送目标指?/span>,把指针内容装?/span>GS.
?/span>: LGS DI,string ;把段地址:偏移地址存到GSDI.
LSS 传送目标指?/span>,把指针内容装?/span>SS.
?/span>: LSS DI,string ;把段地址:偏移地址存到SSDI.
4. 标志传送指?/span>.
LAHF 标志寄存器传?/span>,把标志装?/span>AH.
SAHF 标志寄存器传?/span>,?/span>AH内容装入标志寄存?/span>.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入?/span>.
POPD 32位标志出?/span>.
二、算术运指?/span>
ADD 加法.
ADC 带进位加?/span>.
INC ?/span> 1.
AAA 加法?/span>ASCII码调?/span>.
DAA 加法的十q制调整.
SUB 减法.
SBB 带借位减法.
DEC ?/span> 1.
NEC 求反(?/span> 0 减之).
CMP 比较.(两操作数作减?/span>,仅修Ҏ志位,不回送结?/span>).
AAS 减法?/span>ASCII码调?/span>.
DAS 减法的十q制调整.
MUL 无符号乘?/span>.
IMUL 整数乘法.
以上两条,l果回?/span>AH?/span>AL(字节q算),?/span>DX?/span>AX(字运?/span>),
AAM 乘法?/span>ASCII码调?/span>.
DIV 无符号除?/span>.
IDIV 整数除法.
以上两条,l果回?/span>:
商回?/span>AL,余数回?/span>AH, (字节q算);
?/span> 商回?/span>AX,余数回?/span>DX, (字运?/span>).
AAD 除法?/span>ASCII码调?/span>.
CBW 字节转换为字. (?/span>AL中字节的W号扩展?/span>AH中去)
CWD 字{换ؓ双字. (?/span>AX中的字的W号扩展?/span>DX中去)
CWDE 字{换ؓ双字. (?/span>AX中的字符h展到EAX中去)
CDQ 双字扩展. (?/span>EAX中的字的W号扩展?/span>EDX中去)
三、逻辑q算指o
AND 与运?/span>.
OR 或运?/span>.
XOR 异或q算.
NOT 取反.
TEST 试.(两操作数作与q算,仅修Ҏ志位,不回送结?/span>).
SHL 逻辑左移.
SAL 术左移.(=SHL)
SHR 逻辑右移.
SAR 术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过q位的@环左U?/span>.
RCR 通过q位的@环右U?/span>.
以上八种UM指o,其移位次数可?/span>255?/span>.
UM一ơ时, 可直接用操作?/span>. ?/span> SHL AX,1.
UM>1ơ时, 则由寄存?/span>CLl出UMơ数.
?/span> MOV CL,04
SHL AX,CL
四、串指o
DS:SI 源串D寄存器 :源串变址.
ES I 目标串段寄存?/span>:目标串变址.
CX 重复ơ数计数?/span>.
AL/AX 扫描?/span>.
D标志 0表示重复操作?/span>SI?/span>DI应自动增?/span>; 1表示应自动减?/span>.
Z标志 用来控制扫描或比较操作的l束.
MOVS 串传?/span>.
( MOVSB 传送字W?/span>. MOVSW 传送字. MOVSD 传送双?/span>. )
CMPS 串比?/span>.
( CMPSB 比较字符. CMPSW 比较?/span>. )
SCAS 串扫?/span>.
?/span>AL?/span>AX的内容与目标串作比较,比较l果反映在标志位.
LODS 装入?/span>.
把源串中的元?/span>(字或字节)逐一装入AL?/span>AX?/span>.
( LODSB 传送字W?/span>. LODSW 传送字. LODSD 传送双?/span>. )
STOS 保存?/span>.
?/span>LODS的逆过E?/span>.
REP ?/span>CX/ECX<>0旉?/span>.
REPE/REPZ ?/span>ZF=1或比较结果相{?/span>,?/span>CX/ECX<>0旉?/span>.
REPNE/REPNZ ?/span>ZF=0或比较结果不相等,?/span>CX/ECX<>0旉?/span>.
REPC ?/span>CF=1?/span>CX/ECX<>0旉?/span>.
REPNC ?/span>CF=0?/span>CX/ECX<>0旉?/span>.
五、程序{UL?/span>
1>无条件{UL?/span> (长{U?/span>)
JMP 无条件{UL?/span>
CALL q程调用
RET/RETFq程q回.
2>条g转移指o (短{U?/span>,-128?/span>+127的距d)
( 当且仅当(SF XOR OF)=1?/span>,OP1<OP2 )
JA/JNBE <
抛开压羃法不谈Q我认ؓzip、rar在文件格式上最大的差异在目录表(Table of ContentsQTOCQ:zip有TOCQ而rar没有?/p>
TOCq个词其实是从出版界借用q来的,指的是每一本书正文前面?#8220;目录”Q它的作用地球h都知道:如果惛_速找C中某一内容Q可以先查TOCQ然后按照TOC指明的页码直接翻卛_?/p>
在纸质书里TOC是印刷出来的一张表Q而在电子文g里则是由l构化数据构成的一张表Q它的目的同hZ快速定位:如果x文g中的某一内容Q可以先查TOCQ知道感兴趣的内容在文g的什么位|,直接跌d行了。最常见的运用就是avi、rm{多媒体文gQ播攄时候经常有人在播放条上Ҏ点去跳着看(?#8220;随机讉K”Q,如果没有TOCQ在长达几百兆的文g里来回定位会慢死?/p>
具体到zip文g里,TOC是放在文件尾部的一张表Q里面列Zzip包中每一个文件的属性(文g名、长度等Q和在zip包中的存放位|。如果需要随问zip包中的某一个文Ӟ只需在TOC里找到这个文件的存放位置Q直接蟩q去卛_?/p>
而RAR文g里则没有TOCQ在文g头之后所有文件按序q箋存放?/p>
q种差异造成的结果就是:随机讉K时zip比rar快,而顺序访问时rar比zip快?/p>
所谓随问,是前面说过的随问压~包中某个指定的文g。D一个简单的例子Q一本反~译或下载到的网는子书Q有大量HTML、图像、css、jsQ然后打成压~包。现在要求在不解包的情况下访问其中的面Q可以想象,打开每个HTML面的时候,它所附带的图像、css、js{文件可能随机分布在整个压羃包里Q如果没有TOCQ查找每个文件的时候都要从头开始找Q将会有多慢?所以各位可以理解ؓ什么jar包就是标准zip包,而我也只用zip格式保存反编译出来的电子书、O甅RPDG书等一切可能需要随问的东西?/p>
所谓顺序访问,是整个压~包从头解到。在q方面RARh天然的优ѝ而且Z节省WinRAR列文件的旉Q对于单个RAR我一般都直接通过右键菜单解压~,很少双击压羃包打开再解压。解多个RAR时当焉用BatchUnRar?/p>
׃rar的原作者已l去世,造成q种差异的确切原因我怿已不可考,但我个h猜测可能与DOS时代的备份Y件之争有养I在DOS时代Q电脑硬盘不像现在这样奢侈,20MBq很大了。这L定w用两盒Y?卛_备䆾Q备份成本相Ҏ据本w的价值来说非怽廉。因此在DOS时代Q很多公司和机构都制定有定期盘备䆾政策Q以免因Zh为或非h为的因素 Q早期硬盘可没有如今可靠Q而造成不可挽回的数据损失。在备䆾软g斚wQ虽然微软已l随DOS提供了Backup/Restore工具Q但是他们基本不具备数据压羃能力Q因此在压羃软g中提供备份功能,成为DOS时代的一个时。由于DOS时代的备份介质多Y盘,因此压羃 软g的备份功能其实就转化成如今很常见的一个功能:分卷压羃功能Q即按照软盘定wq行分卷压羃Q然后将分卷压羃文g备䆾QBackupQ到软盘Q需要的时候再解压Q或恢复QRestoreQ到盘?/p>
DOS时代最有名的zip工具是pkzipQ出现得比DOS版的RAR早。在分卷压羃Ӟpkzip按照zip文g规范Q将TOC存放在最后,卛_储在最后一P由此带来如下问题Q?/p>
1、恢复时Q每解压一张盘Q都要先最后一张盘插进Mơ,MơTOC?br>2、只要最后一张盘上的TOC坏了Q就其它盘都是好的Q也不能正常解压?/p>
q两个缺点,其是第一个缺点实在是太臭名昭著了Q因此当时出C非常强烈的改革呼声。在q个关键时刻QDOS版的RAR出现了:不仅压羃率比pkzip高(q点在DOS时代非常重要Q毕竟Y盘又贵容量又)Q而且׃吸取了当时对zip格式的批评,取消了TOCQ因此:
1、在恢复分卷压羃的备份文件时Q不需要频J插入带有TOC的分P按顺序换盘即可?br>2、即使某个分h坏,也可以蟩q,从完好的分卷再开始解压?/p>
׃q些原因Q当然还有其它原因)QRAR推出后迅速取得了成功Qpkzip在DOS时代开始流qP到Windows时代基本消声匿迹。在Windows时代推出的WinzipQ则d攑ּ了分卷压~功能(zip格式永远的痛Q)?而从我看到的源自WinRAR?a target=_blank>UnRAR源代?/font>来看Q现在WinRAR的解压思\明显q是把文件按序从头解到,看来当年备䆾/恢复工具之争的媄响,q真是深q?/p>
在压~算法方面,我觉得rar格式最特色的是固实QsolidQ压~方式。WinRAR v3.42的帮助文件中对固实压~的说明如下Q?br> 举一个简单的例子Q用zip和普通rar压羃一堆jpg文gQ很隑֎下去Q但是用固实压羃方式的rar可以,其原因就在于Qjpg文g本n已经是压~格式了Q单个jpg文g里很隑ֆ 扑ֈ可利用的重复数据Q因此不论是用zipq是普通的rar都很隑ֆ压羃Q因Z们都需要压~的文g分隔开来一个一个处理。但是对于固实rar来说Q是?所有需要压~的jpg文g当作一个整体来压羃Q这些jpg之间存在重复的数据Q如他们都有相同的文件头Q其中包括各U数据表Q等Q这出C可压~的I间。从我看到的资料来看QFlash文g也采用了cM的技术对jpgq行压羃Q如果在Flash文g中用了多个jpg文gQ它们可以共用一个文件头?br> 固实压羃可增加压~性能Q特别是在添加大量的文件的时候,但它也有一些重要的不利因素: 固实压羃的适用场合? 与前面说?#8220;随机讉K”对应Q固实压~的RAR文g可能是世界上最不适合随机讉K的:如果需要访问固实RAR包中的某个文Ӟp从文件头开始解压,一直解到这个文件?/p>
q里的安全性包含几个方面的含义Q文件系l安全性、密码保护安全性和文g数据安全性?/p>
׃制订zip格式规范的时候操作系l本w的文g安全性还没有引v_的重视,因此zip格式只记录最基本的文件属性,包括只读属性等Q没有其它附加的安全属性?/p>
rar格式刚推出的时候,文gpȝ的安全性只能参照DOSQ和zip差不多。但是rar毕竟是一U封闭的格式Q想怎么改作者一个h说了qQ因此当Windows中出现NTFSQƈ且引入扩展的文gpȝ安全属性时Qrar也积极跟q,所以现在应该说rar格式在这斚w比zip??/p>
在zip和rar格式中均提供了密码保护功能,但是密码保护的安全强度不同?/p>
zip׃格式开放、代码开源,因此zip密码破解软g出现得比较早Q也比较多。初期以暴力破解ZQ威胁不大,真正对zip密码安全的致命一Lknown plain textQ已知明文)d法:如果知道加密zip文g中某D内容(密文QciphertextQ解密后的真正内容(明文Qplain textQ,可以反推出zip加密口o。在q种dҎ的威胁,及某些国家的法律对密码技术的限制下, 著名开源组l?a target=_blank>zlib宣布怹攑ּ对加密zip的支持,详见zlib|站上的相关说明Q不q在zlib发行的源代码里仔l找找,q是能找到原来的?解密相关代码Q?/p>
记得rar刚推出的时候也和zip一P虽然不能列出加密文g中的文g内容Q但可以列出加密文g中的文g名。后来大概也是被known plain textd法吓CQ增加了一?#8220;加密文g?#8221;选项Q干脆连加密rar文g里有哪些文g都看不见Q让d者想猜明文都无从猜v?/p>
rar格式比zip晚推出,在安全方面吸取了_的教训,因此采用的是国国家标准与技术局QNational Institute of Standard and Technology, NISTQ推荐的、目前公认安全程度比较高的AES对称加密法 Q密钥长?28位。在ASE被攻破以前(NIST认ؓ30q内无法ȝQ,大家都只能在暴力法上兜圈子,所以密码安全性应该说比zip高。对此WinRAR 3.42的帮助文件是q样描述的: ZIP 格式使用U有加密法?RAR 压羃文g使用更强大的 AES-128 标准加密。如果你需要加密重要的信息Q选择 RAR 压羃文g格式会比较好一些。ؓ了确实的安全性,密码长度h要 8 个字W。不要用Q何语a的单词作为密码,最好是L的随机组合字W和数字Qƈ且要注意密码的大写。请CQ如果你遗失你的密码Q你无法取出加密的文gQ就是 WinRAR 的作者本w也无法解压加密q的文g?/strong> 在数据安全性方面,RAR格式本n支持一U特D的附加信息cdQ叫?#8220;恢复记录”。如果RAR文g有恢复记录,在介质物理损坏或其它原因造成数据丢失ӞWinRAR可以按照“恢复记录”试Ҏ据进行修复。而zip格式无恢复记录,因此在数据安全性方面应该说比RAR弱?/p>
虽然RAR文g本n支持恢复记录Q但是在WinRAR里此选项~省是关闭的Q而打开后会D压羃出来的RAR文g体积增加Q增加的癑ֈ比与讄有关Q,可能会o某些人感C习惯Q我׃D到有人在论坛上抱怨ؓ什么压出来的RAR文g会如此庞大)Q所以这个功能基本上形同虚设?/p>
开放性的Ҏ很明显:zip格式不仅文g格式完全公开Q而且有专门的开源组l提供操作源代码Q跨q_使用也没有多大限Ӟrar格式完全保密Q作者只提供解压所需源代码,不提供压~所需源代?Q跨q_使用有点ȝ?/p>
zip开源组l中Q最出名的是zlib?a target=_blank>InfoZipQ二者各有侧重:zlib偏重对内存缓冲区的压~,因此?a target=_blank>png{开源组l用做内部压~算法,qjava的jarE序内核都来自zlibQ打出来的jar包自然也是一个标准的zip文gQInfoZip偏重Ҏ件的操作 Q包括口令保护)Q应用似乎不如zlibq泛Q但我个得其实它q是满好用的Q前提是需要对它的源代码进行一些必要的修改?/p>
?a target=_blank>pngl织的网中有说到png格式的来历,我觉得也很有意思:做png的一班hQ其实原来都是做gif格式的,但是׃Unisys公司开始对gif格式的核心——LZW压羃法征收专利费,q帮人怒了Q干脆提出png格式Q大l构斚wq是采用分段l构Q但是核心压~算法采用开源的zlibQ压~?效果在多数情况下比gif的LZW更强。由于没有版权限Ӟ在静态图形领域png得到q泛应用Q如果不是及时提出动L持ƈ因此在web上大行其道,我估计gif早就L了?/p>
RAR的解压源代码在其官方|站www.rarlab.com上提供,通常比WinRAR的正式版本晚一点,不过据说是直接从WinRAR的源代码中抠出来的,所以兼Ҏ应该没有什么问题?/p>
以下观点U属个h观点Q仅供参考,不具有如何指导意义:
固实压羃文g?RAR 的一U特D压~方式存储的压羃文gQ它把压~文件中的全部文仉当成一个连l数据流来看待?/strong>
q段说明其实揭示了固实压~格式能够提高压~比的奥U:数据压羃的基?#8220;重复”Q例如aaaabbbq个字符Ԍ里面有重复Q如果表CZؓa4b3Q看h是不是变短了Q这是“数据压羃”?#8220;重复”是一个具有相Ҏ义的概念Q在某一范围内看h没有重复Q或重复不多的数据,把范围扩大,说不定就能找到更多重复的数据了,q就是固实压~的奥秘?/p>
当然天下不会有白吃的午餐Q固实压~方式在提高压羃比的同时Q也有一些限Ӟ在WinRAR v3.42帮助文g中的说法是:
]]>
输入|abc后面跟个回R
本以为屏q应该显C?br>a
a
b
b
c
c
实际上是:
abc
abc
q是因ؓ只有当输入回车时Q系l才认ؓ是输入完?br>
2.上面的代码还有一个问?br>因ؓEOF?1Q所以c=getchar()q一句会出现问题
所以c应该是int c
二、EOF
只有在新的一行输入的时候输入EOF才算是文件结束符
假设输入Q?br>abc^zqwer
输出为:
abc