作者归档:老沙

G31主板 1440 * 900 1680 * 1050驱动

买了个G31的主板,发现没有1440*900和1680*1050分辨率,在网上查了查,发现了这个驱动
原文如下:
Symptom:

Users may be unable to use the native resolution of some displays when using Intel chipset graphics. Resolutions such as 1680×1050 and 1440×900 are not available in graphics properties.

Cause:

The display EDID is not read properly when connecting to a subset of Digital Flat Panel (DFP) displays.

Solution:

Intel has released this driver to specifically address this issue however, there may be side effects to this solution such as longer than normal resume times from standby. This solution will only work with external displays such as DFP displays. This driver is not designed to address issues with Local Flat Panel displays or TV's connected to the system. This driver is provided as is. Intel has not tested, and does not warranty, the operation of the driver for this purpose.

This file is written specifically for the Intel® 946GZ, G31, G33, G35, G41, G43, G45, Q33, Q35, Q43, Q45, G965, Q963, and Q965 Express Chipsets and the Mobile Intel® GM45, GL960, and GM965 Express Chipsets and will not function with any other product. View the README file for installation information and the RELEASE NOTES for driver version details. This driver package contains the version 14.36.3.4990 (Build 6.14.10.4990) drivers for Windows* XP.

The software drivers provided on this page are generic versions, and can be used for general purposes.
However, computer original equipment manufacturers (OEMs) may have altered the features, incorporated
customizations, or made other changes to the software or software packaging they provide. To avoid any
potential installation incompatibilities on your OEM system, Intel recommends that you check with your OEM and
use the software provided via your system manufacturer.
Intel or the computer original equipment manufacturer (OEM) may not provide technical support for some or all
issues that could arise from the usage of this generic version of software drivers.
__________________________________________________________________________
大体就是说intel临时做了这么一个驱动,加入了1440*900与1680*1050分辨率,为什么没有这个分辨率呢?是因为没有正确识别显卡器,并且还说了这个驱动他们也没有测试过,有可能会有问题,自己看着办吧
http://downloadcenter.intel.com/Detail_Desc.aspx?strState=LIVE&lang=eng&ProductID=2102&DwnldID=14416

常用日期函数(delphi)

常用日期函数(delphi)

Day 开头的函数

Unit

DateUtils

function DateOf(const AValue: TDateTime): TDateTime;

描述
使用 DateOf 函数用来把一个 TDateTime 类型的变量转变成一个
只带有日期的 TDateTime 类型变量。
例如:
showmessage(DateTimetostr(dateof(now())));
你得到的是 2003/03/19
而 showmessage(DateTimetostr((now())));
得到的是 2003/03/19 10:50:49

●function DateTimeToStr(DateTime: TDateTime): string;

描述
DateTimeToString 函数将 TDateTime 类型的参数 DateTime 转换成一个
字符串,使用给定的全局变量 ShortDateFormat 的格式,时间部分按照
给定的全局变量 LongTimeFormat 的格式。
其中 DateTime 为零的部分将不会显示出来。

例如:
ShortDateFormat:='yyyy mm dd';
showmessage(DateTimetostr((now())));
你将得到:2003 03 19 10:50:49

●procedure DateTimeToString(var Result: string; const Format: string; DateTime: TDateTime);

描述:
DateTimeToString 方法将TDateTime类型的参数DateTime 按照由参数Format提供的格式
转化成字符串,并保存在Result中。
对于Format的格式类型,请看 Date-Time format strings 的帮助。

例如:
DateTimeToString(result,'yyyy mm dd',now());
那么 result的结果为:2003 03 19 10:50:49

●procedure DateTimeToSystemTime(DateTime: TDateTime; var SystemTime: TSystemTime);

描述:
有时为了调用API函数来使用系统时间,你可以使用 DateTimeToSystemTime 方法,来将一个
TDateTime 类型的时间变量转换成一个 TSystemTime 类型的 系统时间。

●function DateTimeToUnix(const AValue: TDateTime ): Int64;

描述:
使用 DateTimeToUnix 函数来将一个 TDateTime 型时间变量转换成一个相应的 Unix 格式
的日期和时间。
Unix date-and-time values are encoded as the number of seconds that have elapsed
since midnight at the start of January 1, 1970.

●function DateToStr(Date: TDateTime): string;

描述:
使用 DateToStr 函数能得到 TDateTime 日期时间类型的日期部分。日期的转换格式依赖于
全局变量 ShortDateFormat。

●function DayOf(const AValue: TDateTime): Word;

描述:
对于给定的TDateTime类型的日期时间,使用 DayOf 函数能得到该日期是该月份的第几天。
该函数的返回数值在 1 到 31 之间
注意:DayOf 函数得到的结果与 DayOfTheMonth 相同。

例如:
showmessage(inttostr(dayof(now)));
得到的是:19 (今天是 某月19日)

●function DayOfTheMonth(const AValue: TDateTime): Word;

与 DayOf 相同。

●function DayOfTheWeek(const AValue: TDateTime): Word;

描述:
对于给定的TDateTime类型的日期时间,使用 DayOfTheWeek 函数能得到该日期是该星期的
第几天。DayOfTheWeek 函数的返回数值为 1 到 7,其中 1 表示星期一,而 7 表示星期日。
注意:DayOfTheWeek 是 ISO 8601 标准的(此标准为 星期一是一周的第一天)。对于一周
的第一天是星期日的标准,如果想获得星期数,请使用 DayOfWeek 函数。
Tip: To make the return value more readable, use the Day of week constants.

●function DayOfTheYear(const AValue: TDateTime): Word;

描述:
根据给定的日期时间参数AValue,使用 DayOfTheYear 函数能得到在该日期所在的年份中,该
日期按照顺序所计算的天数。因此,作为TDateTime类型的变量 “1月1日”在该函数所得到的
结果为 1 ,“1月2日”所得到的结果为 2,“2月1日”所得到的结果就为 32,依次类推。

●function DayOfWeek(Date: TDateTime): Integer;

Description

DayOfWeek returns the day of the week of the specified date as an integer between
1 and 7, where Sunday is the first day of the week and Saturday is the seventh.

Note: DayOfWeek is not compliant with the ISO 8601 standard, which defines Monday
as the first day of the week. For an ISO 8601 compliant version, use the DayOfTheWeek
function instead.

描述:
按照给定的TDateTime类型的参数Date,DayOfWeek 函数得到一周中的第几天,从1到7。
这里 星期日 是一周的第一天,而 星期六 是第七天。

●function DaysBetween(const ANow, AThen: TDateTime): Integer;

描述:
根据两个TDateTime类型的日期时间变量 ANow 和 AThen,DaysBetween函数能得到两者之间的
天数的差距。
DaysBetween 仅仅根据天数的不同来计算。因此,对于 1999年12月31日 下午11点59分 到
2000年1月1日 11点58分,该函数得到的结果是 0,因为两者之间的时间差别还差 1 分钟才到
1 天。

●function DaysInAMonth(const AYear, AMonth: Word): Word;

描述:
对于各定的 年份和月份,DaysInAMonth 函数能得到 该月份的总天数。
年份应该为 从 1 到 9999
月份应该为 从 1 到 12

●function DaysInAYear(const AYear: Word): Word;

描述:
对于给定的年份,DaysInAYear函数能得到该年份的总天数。
年份应该为 1 到 9999。

●function DaysInMonth(const AValue: TDateTime): Word;

描述:
根据给定的TDateTime类型的时间日期参数AValue,DaysInMonth函数能得到该月份的总天数。

●function DaysInYear(const AValue: TDateTime): Word;

描述:
根据给定的TDateTime类型的时间日期参数AValue,DaysInYear函数能得到该年份的总天数。

●function DaySpan(const ANow, AThen: TDateTime): Double;

描述:
根据两个TDateTime类型的日期时间参数ANow和AThen,DaySpan能得到在天数上的差距。
与 DaysBetween 函数不同,DaysBetween 函数 只是计算 整的天数,而 DaySpan函数会
将不足一天的数也得到。
注意:此函数返回的数值为 Double 型。

☆ Month 开头的函数

●function MonthOf(const AValue: TDateTime): Word;

描述:
根据给定的TDateTime类型的时间日期参数AValue,MonthOf函数能得到该年份的该月份数。
MonthOf返回数值为 1 到 12。
注意:MonthOf函数得到的数值与MonthOfTheYear函数相同

●function MonthOfTheYear(const AValue: TDateTime): Word;

与MonthOf函数相同。

●function MonthsBetween(const ANow, AThen: TDateTime): Integer;

描述:
根据两个给定的TDateTime类型的参数ANow和AThen,MonthsBetween函数能得到两个日期在月份
上差距数。因为月份的天数是不同的,所以 MonthsBetween 函数返回的是一个近似值,该近似
值基于每个月份为 30.4375 天。不足一个月的数字将不被计算。
因此,例如,对于 2月1日 到 2月28日,MonthsBetween 返回的数值为 0。
同样,对于 2月1日 到 3月1日,MonthsBetween 返回的数值也是 0。

●function MonthSpan(const ANow, AThen: TDateTime): Double;

描述:
根据两个给定的TDateTime类型的参数ANow和AThen,MonthsBetween函数能得到两个日期在月份
上差距数。因为月份的天数是不同的,所以 MonthsBetween 函数返回的是一个近似值,该近似
值基于每个月份为 30.4375 天。与 MonthsBetween 函数不同,MonthsBetween函数不计算不足
一个月的数字,MonthSpan函数将会得到不足一个月的数字。
注意:此函数返回的类型为 Double

●function MonthStr(DateTime: TDateTime): string;

Description

HTTP me

ssage headers permit several formats for the representation of date and time
values. MonthStr converts a TDateTime value into a string representing the month.
MonthStr allows server applications to work with date values taken from HTTP request
messages, without worrying about the details of how they are formatted.

☆ Week 开头的函数

●function WeekOf(const AValue: TDateTime): Word;

描述:
根据TDateTime类型的日期时间参数AValu,WeekOf函数会得到该星期为一年的第几个
星期。

●function WeeksInAYear(const AYear: Word): Word;

描述:
WeeksInAYear 函数根据年份得到在该年份中共包含多少个星期。

●function WeeksBetween(const ANow, AThen: TDateTime): Integer;

描述:
根据两个TDateTime类型的日期时间参数ANow和AThen,WeeksBetween函数将得到这两个时间在
星期上的差数。如果差数不足一个星期,则忽略掉。

●function WeekSpan(const ANow, AThen: TDateTime): Double;

描述:
根据两个TDateTime类型的日期时间参数ANow和AThen,WeeksBetween函数将得到这两个时间在
星期上的差数。如果差数不足一个星期,则WeekSpan函数不会忽略掉。
注意:此函数的返回类型为 Double

☆ Year 开头的函数

●function YearOf(const AValue: TDateTime): Word;

描述:
根据给定的TDateTime类型的日期时间参数AValue,YearOf函数能得到该日期的年份数字。
YearOf函数返回的数值为从 1 到 9999

●function YearsBetween(const ANow, AThen: TDateTime): Integer;

描述:
根据两个给定的TDateTime类型的参数ANow和AThen,YearsBetween函数能得到两个日期在年份
上差距数。因为年份的天数是不同的,所以 YearsBetween 函数返回的是一个近似值,该近似
值基于每年的天数为 365.25 天。不足的一年的差距将不会被计算。
因此例如:对于 1月1日和12月31日,如果这两个日期在同一年,则 YearsBetween 返回数值
为 0;如果这两个日期在临近的年份,则 YearsBetween 函数返回数值为 1。

●function YearSpan(const ANow, AThen: TDateTime): Double;

描述:
根据两个给定的TDateTime类型的参数ANow和AThen,YearsBetween函数能得到两个日期在年份
上差距数。因为年份的天数是不同的,所以 YearsBetween 函数返回的是一个近似值,该近似
值基于每年的天数为 365.25 天。与 YearsBetween 函数不同,YearsBetween函数将忽略掉不
足一年的数字,而 YearSpan 将计算不足一年的数字。
注意:该函数返回类型为Double

●function Yesterday: TDateTime;

描述:
Yesterday函数能得到当前日期的前一天的日期,返回数值中不包括时间部分。
例如:
当前日期是 2003/3/19
则 showmessage(datetimetostr(Yesterday));
将得到 2003/3/18

☆日期的合成
●function EncodeDate(Year, Month, Day: Word): TDateTime;

描述:
EncodeDate函数将根据参数 年份、月份、日子 而得到一个TDateTime类型的时间变量。

●function EncodeDateDay(const AYear, ADayOfYear: Word): TDateTime;

描述:
EncodeDateDay将根据参数年份和天数,而得到一个TDateTime类型的时间变量。
其中AYear 为 1 到 9999。
ADayOfYear 为日子在该年份顺序排列的天数,例如,1月1日时,ADayOfYear为1,
2月2日时,ADayOfYear为2,3月1日时,ADayOfYear为32。

●function EncodeDateMonthWeek(const AYear, AMonth, AWeekOfMonth: Word; const ADayOfWeek: Word =

1): TDateTime;

描述:
EncodeDateMonthWeek 函数将根据参数 年份、月份、星期数,星期几,来得到一个TDateTime类型
的时间变量。
其中AYear 为 1 到 9999。
其中AMonth 为 1 到 12。
AWeekOfMonth是在该月份的星期数,1 表示第一个星期,可能包含4天或更多的天数。
注意,一个月的第一天如果是 星期5,星期6或星期日,用表示这三天的AMonth数值必须设定
为上一个月份的数字,同时 AWeekOfMonth 要设为在上一个月所在的星期数。
同样,如果一个月的最后一天是 星期1,星期2,或星期3,那么用表示这三天的AMonth数值
必须设定为下一个月份的数字,同时 AWeekOfMonth 为 1。
ADayOfWeek表示星期几,星期一为1,星期二为2。

●function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond:

Word):TDateTime;

描述:
EncodeDateTime 根据参数 年份、月份、日子、小时、分、秒、毫秒 来得到一个TDateTime类型
日期时间。

●function EncodeDateWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word = 1): TDateTime;

描述:

EncodeDateWeek 根据参数 年份、星期数、星期几 来得到一个TDateTime类型日期时间。

AWeekOfYear是在该年份的星期数,1 表示第一个星期,可能包含4天或更多的天数。
注意,一年的第一天如果是 星期5,星期6或星期日,用表示这三天的AYear数值必须设定
为上一个年份的数字,同时 AWeekOfYear 要设为在上一个年所在的星期数。
同样,如果一年的最后一天是 星期1,星期2,或星期3,那么用表示这三天的AYear数值
必须设定为下一个年份的数字,同时 AWeekOfYear 为 1。
ADayOfWeek表示星期几,星期一为1,星期二为2。

●function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;

描述:
EncodeTime函数根据参数 小时、分、秒、毫秒 得到个一个TDateTime数值。

☆日期的分解

●procedure DecodeDate(Date: TDateTime; var Year, Month, Day: Word);

描述:
DecodeDate从一个TDateTime类型参数Date中分解出得到年份、月份、日子。

●procedure DecodeDateDay(const AValue: TDateTime; out AYear, ADayOfYear: Word);

描述:
DecodeDateDay 方法会根据TDateTime类型参数AValue 得到相应的年份和日期总数。
ADayOfYear:1月1日,此数值为1;1月2日,此数值为2。

●procedure DecodeDateMonthWeek(const AValue: TDateTime; out AYear, AMonth, AWeekOfMonth,

ADayOfWeek: Word);

描述:
DecodeDateMonthWeek方法根据TDateTime类型参数AValue 得到相应的年份、月份、月份中的第几个
星期、星期几
AYear:年份
AMonth:月份,1 到 12
AWeekOfMonth:在该月份中的第几个星期
ADayOfWeek:星期几。星期一为1。

●procedure DecodeDateTime(const AValue: TDateTime; out AYear, AMonth, ADay, AHour, AMinute,

ASecond, AMilliSecond: Word);

描述:
DecodeDateTime 方法根据TDateTime类型参数AValue 得到相应的年份、月份、日子、小时、分、秒、
毫秒。

●procedure DecodeDateWeek(const AValue: TDateTime; out AYear, AWeekOfYear, ADayOfWeek: Word);

描述:
DecodeDateWeek方法根据TDateTime类型参数AValue 得到相应的年份、在该年中的第几个星期、星期几。

静态数组的定义方法

静态数组的定义方法
//1. 标准方法:
var
MyArr: array[0..10] of Integer; //定义静态数组
——————————————————————————–

//2. 可以使用非0下标:
var
MyArr: array[9..10] of Integer; //不能提倡,这样不容易与系统函数沟通
——————————————————————————–

//3. 根据预定义类型来声明数组:
type
TMyArr = array[0..10] of Integer; //先定义一个数组类型
var
MyArr: TMyArr; //再定义静态数组
——————————————————————————–

//4. 在非过程区可以直接赋值:
var
MyArr: array[0..2] of Integer = (11,22,33);
——————————————————————————–

//5. 多维数组:
var
MyArr: array[0..2, 0..2] of Integer;
begin
//使用
MyArr[1,2] := 100;
end;
——————————————————————————–

//6. 根据子界定义数组:
type
TRange = 0..10;
var
MyArr: array[TRange] of Integer;
——————————————————————————–

//7. 根据枚举定义数组:
type
TEnums = (Enum1,Enum2,Enum3);
var
MyArr: array[TEnums] of string;
begin
MyArr[Enum1] := '万一';
ShowMessage(MyArr[Enum1]); //万一
end;
——————————————————————————–

//8. 根据其他类型定义数组:
var
MyArr: array[Byte] of Char;
begin
MyArr[255] := #65;
ShowMessage(MyArr[255]); //A
end;

//应尽量不使用内建类型,可以新建类型:
type
TNewByte = Byte;
var
MyArr: array[TNewByte] of Char;
begin
MyArr[255] := #65;
ShowMessage(MyArr[255]); //A
end;

//也可以使用类型别名:
type
TChar = type Char;
var
MyArr: array[TChar] of Byte;
begin
MyArr['C'] := 255;
ShowMessage(IntToStr(MyArr['C'])); //255
end;

//同时定义类型:
type
MyRec = record
s: string;
r: Real;
b: Byte;
end;
var
Arr1: array[0..100] of MyRec;
Arr2: array[0..100] of record s: string; r: Real; b: Byte; end; //可以直接这样定义
Arr3: packed array[0..100] of MyRec; //压缩数组定义, 好像没有区别?

汉字转16进制(网页上的%)

写一个程序,要把汉字转成网址里的%什么什么的
比如"小杰的博客"转成"%D0%A1%BD%DC%B5%C4%B2%A9%BF%CD"

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm2 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
mName:array[0..255] of byte;
display:string;
i:byte;
begin
zeromemory(@mName,256);
getwindowtextA(edit1.Handle ,@mName,sizeof(mName));
display:='';
i:=0;
while mName[i]<>0 do
Begin
display:=display+'%'+inttohex(mName[i],2);
inc(i);
End;
edit2.Text:=display;
end;

end.

其它内存管理函数

1.填充和移动内存

mov esi,offset szSource
mov edi,offset szDest
mov ecx,dwSize
cld
rep movsb

以上代码实现从szSource开始的dwSize大小的内存块移动到szDest处

xor eax,eax
mov edi,offset szDest
mov ecx,dwSize
cld
rep stosb

以上代码实现szDest处开始的dwSize字节填充为0,如果把xor eax,eax换成mov al,xx 那上边的代码将实现将内存块填充为xx

以上功能对应的API如下:

invoke RtlMoveMemory,offset szDest,offset szSource,dwSize ;移动内存
invoke RtlFillMemory,offset szDest,dwSize,dbFill ;以dbFill填充内存块
invoke RtlZeroMemory,offset szDest,dwSize ;以0填充内存块

2.内存状态测试

invoke IsBadCodePtr,lpMemory
invoke IsBadReadPtr,lpMemory,dwSize
invoke IsBadWritePtr,lpMemory,dwSize
invoke IsBadStringPtr,lpMemory,dwSize

IsBadCodePtr:函数测试指针指向的单个字节是否可读,如果可读返回0,否则返回非0值
IsBadReadPtr:测试某段内存是否可读,如果这段内存的所有字节全可读则返回0,否则返回非0值
IsBadWritePtr:测试某段内存是否可写,如果内存段全都可写则返回0,否则返回非0值
IsBadStringPtr:测试一个指向以0结尾的字符串是否可读,dwSize为字符串最大长度,如果字符串包含结尾的0全是可读的,返回0,否则返回非0值,缓冲区中剩余的字节则不予测试

堆管理函数

堆管理函数
1.私有堆的创建和释放
私有堆的创建

invoke HeapCreate,flOptions,dwInitialSize,dwMaximumSize
.if eax && (eax<0c0000000h)
mov hHeap,eax
.endif

flOptions指定堆属性,有两个值
HEAP_NO_SERIALIZE:标志私有堆不进行独占检测
HEAP_GENERATE_EXCEPTIONS:指定函数失败的返回值,不指定失败返回NULL
dwInitialSize指定创建堆时分配的物理内存
dwMaximumSize为堆自动扩展的最大值.为0则没有最大限制,非0时在堆中申请的内存块不能大于7FFF8h(524K)

私有堆的释放

invoke HeapDestroy,hHeap

将释放堆中所有的内存块.成功运行返回TRUE,当进程终止时系统也会自动调用此函数

2.堆中分配和释放内存块
堆中分配内存块

invoke HeapAlloc,hHeap,dwFlags,dwBytes
.if eax && (eax<0c0000000h)
mov lpMemory,eax
.endif

hHeap:是创建堆时的句柄
dwFlags有三个值
HEAP_NO_SERIALIZE:不进行独占检测,如果创建堆时用了,这里就可以省了
HEAP_GENERATE_EXCEPTIONS:失败返回出错原因,而不仅是一个NULL,创建堆时用了,这里也可以省了
HEAP_ZERO_MEMORY:将分配内存用0初始化
dwBytes:是要分配的内存块的字节数
分配成功返回值是指向内存块第一个字节的指针,失败返回错误代码或NULL,要看dwFlags
STATUS_NO_MEMORY:取值为0c0000017h表示内存不够
STATUS_ACCESS_VIOLATION:取值为0c0000005h表示参数不正确或堆被破坏
在堆中分配内存块只能是固定地址的内存块.

堆中释放内存块

invoke HeapFree,hHeap,dwFlags,lpMemory

hHeap:堆句柄
dwFlags:可以使用HEAP_NO_SERIALIZE
lpMemory:是HeapAlloc函数返回的内存块指针
成功返回非0值,失败返回0

堆中调整内存块大小

invoke HeapReAlloc,hHeap,dwFlags,lpMemory,dwBytes
.if eax && (eax<0c0000000h)
mov lpMemory,eax
.endif

hHeap:堆句柄
dwFlags四个值
HEAP_GENERATE_EXCEPTIONS:返回值
HEAP_NO_SERIALIZE:独占检测
HEAP_ZERO_MEMORY:初始化为0
HEAP_REALLOC_IN_PLACE_ONLY:分配内存时不可移动内存块,使用此标志,指针必定和原来相同
lpMemory:为堆中内存块的指针
dwBytes:要改变的内存块的大小的字节数

3.其它堆管理函数
HeapLock,HeapUnlock,GetProcessHeaps,GetProcessHeap,HeapCompact,HeapSize,
HeapValidate,HeapWalk.

invoke GetProcessHeaps,NumberOfHeaps,lpHeaps

NumberOfHeaps:指定了缓冲区可以存放句柄的数量
lpHeaps:是一个指针,指向用来接收堆句柄的缓冲区,缓冲区长度应该等于NumberOfHeaps*4
执行后函数返回进程中所有堆的句柄到缓冲区中,也包括默认堆的句柄

.repeat
invoke HeapWalk,hHeap,lpEntry
push eax
pop eax
.until !eax

hHeap:是堆的句柄
lpEntry:指向一个句含有PROCESS_HEAP_ENTRY结构的缓冲区
每次执行返回一个PROCESS_HEAP_ENTRY的结构块信息,如果还有其他的内存块,函数返回TRUE,程序一直循环调用直到返回FALSE为止,在多线程的程序中使用,必须先使用HeapLock函数,否则会调用失败.

invoke HeapValidate,hHeap,dwFlags,lpMemory

验证堆的完整性或堆中某个内存块的完整性
lpMemory为NULL函数顺序验证堆中所有的内存块,如果lpMemory指定了一个内存块,则只验证这个内存块
dwFlags:可以指定HEAP_NO_SERIALIZE,独占标志
如果所有内存块都完好无损,返回非0值,否则返回0

invoke HeapLock,hHeap
invoke HeapUnlock,hHeap

销定和解销堆,主要用于线程同步,成功返回非0值,否则返回0,在程序中一般用HEAP_NO_SERIALIZE来控制

invoke HeapCompact,hHeap,dwFlags

合并堆中的空闲内存块并释放不在使用中的内存页面

invoke HeapSize,hHeap,dwFlags,lpMemory

返回堆中某个内存块大小lpMemory指定了需要返回大小的内存块,成功返回内存块大小,失败返回-1

虚拟内存管理函数

虚拟内存管理函数
VirtualAlloc,VirtualFree – 地址空间分配和释放
VirtualLock,VirtualUnlock – 对内存页进行销定和解锁
VirtualQuery,VirtualQueryEx – 查询内存页的状态
VirtualProtect,VirtualProtectEx – 改变内存页的保护属性

1.保留和释放地址空间

invoke VirtualAlloc,lpAddress,dwSize,flAllocationType,flProtect

lpAddress:指定要保留或提交的内存地址,为NULL时系统自动分配一个地址
dwSize:表示函数分配的地址范围大小,单位字节
flAlloctiontype可以取的标志有三个
MEM_COMMIT:为指定地址空间提交物理内存
MEM_RESERVE:保留指定地址空间,不分配物理内存
MEM_TOP_DOWN:尽可能使用高端的地址空间
flProtect可以取的标志有六个
PAGE_READONLY:为以提交的物理内存的址空间设定只读属性
PAGE_READWRITE:为以提交的物理内存设定为可读写属性
PAGE_EXECUTE:设定为可执行属性
PAGE_EXECUTE_READ:为物理内存设定可读和可执行属性
PAGE_EXECUTE_READWRITE:为内存设定为可读写和可执行属性
PAGE_NOACCESS:为保留的地址空间设定为不可存取模式
函数执行成功会返回一个指向被保留地址范围开始位置的指针,执行失败返回NULL

invoke VirtualFree,lpAddress,dwSize,dwFreeType

lpAddress与dwSize:为指定地址和空间的大小,与VirtualAlloc相同
dwFreeType可以的标志有两个
MEM_DECOMMIT:为一个以提交的物理内存的地址空间解除提交
MEM_RELEASE:释放保留的址址空间

例:

invoke VirtualAlloc,NULL,10485760,MEM_RESERVE,PAGE_NOACCESS
.if eax
mov lpAddress,eax
.endif

空间的分配方式用MEM_RESERVE保留指定地址空间,不分配物理内存,是无法访问的,所以保护属性必须使用PAGE_NOACCESS,以上代码保留10M大小的空间,保留地址并不保证将来有可用内存来提交给这些地址

invoke VirtualFree,lpAddress,0,MEM_RELEASE

lpAddress是VirtualAlloc返回的指针,释放保留内存时dwSize必须为0,释放一个地址空间中的所有页面必须是同一个状态,否则释放操作会失败.

2.使用保留的地址空间

invoke VirtualAlloc,lpAddress,4096,MEM_COMMIT,PAGE_READWRITE
.if eax
mov lpMemory,eax
.endif

保留地址内存可以按一页的大小被分次提交,也可以一次提交所有的保留地址,当内存被提交时,可以被分配为物理内存页,也有可以被分配在页文件中,在提交时lpAddress不能为NULL,要指定一个特定的地址来准确地指示被保留的哪一页会被提交.属性可以设定成可访问的,成功返回第一页起始线程的地址,失败返回NULL

invoke VirtualAlloc,NULL,dwSize,MEM_RESERVE or MEM_COMMIT,PAGE_READWRITE
.if eax
mov lpMemory,eax
.endif

这种方法与GlobalAlloc函数直接分配一块内存没有多大区别,只是可以指定分配的内存块地址

invoke VirtualFree,lpMemory,dwSize,MEM_DECOMMIT

以上代码为解除提交,让它们从提交状态返回到保留状态,函数的操作对象是整个页面,如果指定的内存范围不是整个页面,函数会自动将整个范围同属一个页面的地址全部解除提交.

3.内存页的保护和锁定

invoke VirtualProtect,lpAddress,dwSize,flNewProtect,lpflOldProtect

flNewProtect:是新的保护方式,取值可以参考VirtualAlloc的flProtect的标志
lpOldProtect:是指向一个双字的指针,函数会在这里返回原来的保护方式,如果不需要可以设置为NULL

invoke VirtualLock,lpAddress,dwSize
invoke VirtualUnlock,lpAddress,dwSize

锁定的意思是将指定内存页保留在物理内存中,不许将它交换到磁盘页文件中,同时锁定的内数不能超过30个

超类化 罗老板的源码

super.asm:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .386
    .model flat, stdcall
    option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include    windows.inc
include    user32.inc
includelib  user32.lib
include    kernel32.inc
includelib  kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN  equ  1000
DLG_MAIN  equ  1000
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .data?

hInstance  dd  ?
hWinMain  dd  ?
lpOldProcEdit  dd  ?

    .const
szAllowedChar  db  '0123456789ABCDEFabcdef',08h
szEditClass  db  'Edit',0
szClass    db  'HexEdit',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; HexEdit控件的新窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcEdit  proc  uses ebx edi esi hWnd,uMsg,wParam,lParam

    mov  eax,uMsg
    .if  uMsg ==  WM_CHAR
      mov  eax,wParam
      mov  edi,offset szAllowedChar
      mov  ecx,sizeof szAllowedChar
      repnz  scasb
      .if  ZERO?
        .if  al > '9'
          and  al,not 20h
        .endif
        invoke  CallWindowProc,lpOldProcEdit,hWnd,uMsg,eax,lParam
        ret
      .endif
    .else
      invoke  CallWindowProc,lpOldProcEdit,hWnd,uMsg,wParam,lParam
      ret
    .endif
    xor  eax,eax
    ret

_ProcEdit  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 基于Edit类建立一个新的类:HexEdit
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SuperClass  proc
    local  @stWC:WNDCLASSEX

    mov  @stWC.cbSize,sizeof @stWC
    invoke  GetClassInfoEx,NULL,addr szEditClass,addr @stWC
    push  @stWC.lpfnWndProc
    pop  lpOldProcEdit
    mov  @stWC.lpfnWndProc,offset _ProcEdit
    push  hInstance
    pop  @stWC.hInstance
    mov  @stWC.lpszClassName,offset szClass
    invoke  RegisterClassEx,addr @stWC
    ret

_SuperClass  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain  proc  uses ebx edi esi hWnd,wMsg,wParam,lParam

    mov  eax,wMsg
;********************************************************************
    .if  eax ==  WM_CLOSE
      invoke  EndDialog,hWnd,NULL
;********************************************************************
    .else
      mov  eax,FALSE
      ret
    .endif
    mov  eax,TRUE
    ret

_ProcDlgMain  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>&g

t;>>>>>>>>>>>>>>>>>>>
start:
    invoke  GetModuleHandle,NULL
    mov  hInstance,eax
    invoke  _SuperClass
    invoke  DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
    invoke  ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    end  start

super.rc:

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include    <resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define  ICO_MAIN  1000
#define  DLG_MAIN  1000
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN  ICON    "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN DIALOG 107, 102, 126, 82
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "SuperClass"
FONT 9, "宋体"
{
CONTROL "",-1,"HexEdit",ES_LEFT | WS_BORDER | WS_TABSTOP,5,5,115,12
CONTROL "",-1,"HexEdit",ES_LEFT | WS_BORDER | WS_TABSTOP,5,20,115,12
CONTROL "",-1,"HexEdit",ES_LEFT | WS_BORDER | WS_TABSTOP,5,35,115,12
CONTROL "",-1,"HexEdit",ES_LEFT | WS_BORDER | WS_TABSTOP,5,50,115,12
CONTROL "",-1,"HexEdit",ES_LEFT | WS_BORDER | WS_TABSTOP,5,65,115,12
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

标准内存管理函数

标准内存管理函数
GlobalAlloc,GlobalFree,GlobalReAlloc,GlobalLock,GlobalUnlock,GlobalDiscard,GlobalFlags,GlobalHandle,GlobalSize

1.固定的内存块

invoke GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,dwBytes
.if eax
mov lpMemory,eax
.endif

申请失败eax返回NULL,成功返回指向申请内存起始地址的指针.GPTR

释放固定内存块

invoke GlobalFree,lpMemory

释放成功返回NULL,返否返回输入的lpMemory

改变内存块大小

invoke GlobalReAlloc,lpMemory,dwBytes,uFlags
.if eax
mov lpNewMemory,eax
.endif

lpMemory是先前申请的内存指针,dwBytes是新大小,uFlags可以是空
uFlags来规定是否允许移动内存块,当为GMEM_MOVEABLE选项时,如果需要移动内存块windows会在其它地方新开一个内存块,并把原来的内容自动复制到新内存中,这时函数会返回一个新的指针,原来的指针作废
如果不指定GMEM_MOVEABLE,当后面的空间不足时,函数失败并返回NULL,原来的指针继续有效.
改变内存大小时,建意使用以下代码

invoke GlobalReAlloc,lpMemory,dwBytes,GMEM_ZEROINIT or GMEM_MOVEABLE
.if eax
mov lpMemory,eax
.endif

2.可移动的内存块
申请可移动的内存块

invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,dwBytes
.if eax
mov hMemory,eax
.endif

GMEM_MOVEABLE or GMEM_ZEROINIT = GHND
申请失败eax返回NULL,成功返回一个句柄.可移动内存块不能超过65536个,固定内存块数量无限制

销定可移动内存:

invoke GlobalLock,hMemory
.if eax
mov lpMemory,eax
.endif

销定失败返回NULL,成功返回一个指针
当不使用时要解销

invoke GlobalUnlock,hMemory

解销成功返回非0值

释放可移动内存块

invoke GlobalFree,hMemory

释放成功返回NULL

调整可移动内存块大小

invoke GlobalReAlloc,hMemory,dwBytes,GHND

如果成功返回hMemory,失败返回NULL
注意最好先解销再调整大小

3.可丢弃的内存块
可丢弃的内存块必须是可移动的内存块

invoke GlobalAlloc,GHND or GMEM_DISCARDABLE,dwBytes
.if eax
mov hMemory,eax
.endif

如果GlobalLock内存返回NULL,说明内存以被丢弃了,但句柄还是有效的,如果还要使用这个句柄,可以使用
GlobalReAlloc来重新分配内存,当销定计数为0时,可以使用GlobalDiscard主动将它丢弃.

4.获取内存块的信息
GlobalFlags主要用来取得可移动内存的计数,也可以检测可丢弃内存是否被丢弃.

invoke GlobalFlags,hMemory
and eax,GMEM_LOCKCOUNT
mov dwLockCount,eax

返回值不是GMEM_INVALID_HANDLE说明调用成功,这时返回值低8位是内存块的销定计数
GMEM_DISCARDABLE 表示内存块是可丢弃内存块
GMEM_DISCARDED 表示内存块以被失弃

GlobalHandle可以从GlobalLock得到的lpMemory值获取对应的hMemory
GlobalSize可以获取一个内存块的尺寸

子类化 罗老板的源码

subclass.asm:

    .386
    .model flat, stdcall
    option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include    windows.inc
include    user32.inc
includelib  user32.lib
include    kernel32.inc
includelib  kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN  equ  1000
DLG_MAIN  equ  1000
IDC_HEX    equ  1001
IDC_DEC    equ  1002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .data?
hInstance  dd  ?
hWinMain  dd  ?
dwOption  dd  ?
lpOldProcEdit  dd  ?

    .const
szFmtDecToHex  db  '%08X',0
szFmtHexToDec  db  '%u',0
szAllowedChar  db  '0123456789ABCDEFabcdef',08h
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; IDC_HEX编辑框的新窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcEdit  proc  uses ebx edi esi hWnd,uMsg,wParam,lParam

    mov  eax,uMsg
    .if  uMsg ==  WM_CHAR
      mov  eax,wParam
      mov  edi,offset szAllowedChar
      mov  ecx,sizeof szAllowedChar
      repnz  scasb
      .if  ZERO?
        .if  al > '9'
          and  al,not 20h
        .endif
        invoke  CallWindowProc,lpOldProcEdit,hWnd,uMsg,eax,lParam
        ret
      .endif
    .else
      invoke  CallWindowProc,lpOldProcEdit,hWnd,uMsg,wParam,lParam
      ret
    .endif
    xor  eax,eax
    ret

_ProcEdit  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 计算16进制到10进制
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_HexToDec  proc
    local  @szBuffer[512]:byte

    invoke  GetDlgItemText,hWinMain,IDC_HEX,addr @szBuffer,sizeof @szBuffer
    lea  esi,@szBuffer
    cld
    xor  eax,eax
    mov  ebx,16
    .while  TRUE
      movzx  ecx,byte ptr [esi]
      inc  esi
      .break  .if ! ecx
      .if  cl > '9'
        sub  cl,'A' – 0ah
      .else
        sub  cl,'0'
      .endif
      mul  ebx
      add  eax,ecx
    .endw
    invoke  wsprintf,addr @szBuffer,addr szFmtHexToDec,eax
    invoke  SetDlgItemText,hWinMain,IDC_DEC,addr @szBuffer
    ret

_HexToDec  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 计算10进制到16进制
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_DecToHex  proc
    local  @szBuffer[512]:byte

    invoke  GetDlgItemInt,hWinMain,IDC

_DEC,NULL,FALSE
    invoke  wsprintf,addr @szBuffer,addr szFmtDecToHex,eax
    invoke  SetDlgItemText,hWinMain,IDC_HEX,addr @szBuffer
    ret

_DecToHex  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain  proc  uses ebx edi esi hWnd,wMsg,wParam,lParam

    mov  eax,wMsg
;********************************************************************
    .if  eax ==  WM_CLOSE
      invoke  EndDialog,hWnd,NULL
;********************************************************************
    .elseif  eax ==  WM_INITDIALOG
      mov  eax,hWnd
      mov  hWinMain,eax
      invoke  SendDlgItemMessage,hWnd,IDC_HEX,EM_LIMITTEXT,8,0
      invoke  SendDlgItemMessage,hWnd,IDC_DEC,EM_LIMITTEXT,10,0
      invoke  GetDlgItem,hWnd,IDC_HEX
      invoke  SetWindowLong,eax,GWL_WNDPROC,addr _ProcEdit
      mov  lpOldProcEdit,eax
;********************************************************************
    .elseif  eax ==  WM_COMMAND
      mov  eax,wParam
      .if  ! dwOption
        mov  dwOption,TRUE
        .if  ax ==  IDC_HEX
          invoke  _HexToDec
        .elseif  ax ==  IDC_DEC
          invoke  _DecToHex
        .endif
        mov  dwOption,FALSE
      .endif
    .else
      mov  eax,FALSE
      ret
    .endif
    mov  eax,TRUE
    ret

_ProcDlgMain  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
    invoke  GetModuleHandle,NULL
    mov  hInstance,eax
    invoke  DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
    invoke  ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    end  start

subclass.rc

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include    <resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define  ICO_MAIN  1000
#define  DLG_MAIN  1000
#define IDC_HEX    1001
#define IDC_DEC    1002
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN  ICON    "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN DIALOG 107, 102, 129, 42
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Hex <> Dec"
FONT 9, "宋体"
{
LTEXT "Hex", -1, 7, 9, 15, 8
EDITTEXT IDC_HEX, 27, 7, 94, 12
LTEXT "Dec", -1, 7, 26, 15, 8
EDITTEXT IDC_DEC, 27, 24, 94, 12, ES_NUMBER
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>