在破解用Delphi写的软件时,经常会碰到一些诸如System.@LStrCmp、System.@LStrAddRef之类的函数。实际上它们都是Delphi内部用来处理字符串的过程/函数。这些函数在System里都可以找到。但是它们的参数和返回值有点特别。于是抽空看了一下system.pas。
首先,这些函数名都有一定的格式:
_xStryyy
其中x可以是字符P、L、W。P代表该函数是处理传统Pascal字符串的,L代表该函数是处理长字符串的,W当然就是Unicode了。yyy就是表示函数的实际作用了。比如_PStrCat就是表示传统Pascal字符串的连接函数。大家可以查阅system.pas来验证一下。不过一般不大见到W开头的函数。
下面是经过整理的结果,算是为大家提供一个方便。说明一下,列表不全,但没列出来的函数完全可以见名知意。当然,前提是你看完列表。
另外,需要注意的是,对于在堆栈里的返回值,一般以EBP引用。如果你看到函数调用后下一条语句是MOV xxx,[EBP+yy],那通常就是保存返回值了。特别是_LStrCopy。
名称 |
参数 |
返回值 |
作用 |
等价形式 / 备注 |
_PStrCat |
EAX :目标字符串 EDX :源字符串 |
EAX |
连接两个 Pascal 字符串 |
s:=copy(s+s1,1,255) |
_PStrNCat |
EAX :目标字符串 EDX :源字符串 CL :结果字符串最大长度 |
EAX |
连接两个 Pascal 字符串 |
s:=copy(s+s1,1,n) |
_PStrCpy |
EAX :目标字符串 EDX :源字符串 |
EAX |
Pascal 字符串复制 |
s:=s1 |
_PStrNCpy |
EAX :目标字符串 EDX :源字符串 CL :结果字符串最大长度 |
EAX |
Pascal 字符串复制 |
s:=copy(s1,1,n) |
_PStrCmp |
EAX :左字符串 EDX :右字符串 |
标志位 Z |
Pascal 字符串比较 |
if s=s1 |
_AStrCmp |
EAX :左字符串 EDX :右字符串 ECX :要比较的字符个数 |
标志位 Z |
Ansi 字符串比较 |
if s=s1 |
procedure _LStrClr(var S: AnsiString); |
EAX :字符串 |
清空字符串 |
s:='' |
|
Procedure _LStrArrayClr(var str: AnsiString; cnt: longint); |
EAX :字符串数组指针 EDX :数组长度 |
清空字符串数组 |
||
procedure _LstrAsg(var dest: AnsiString; source: AnsiString) |
EAX :目标字符串 EDX :源字符串 |
复制 Ansi 字符串 |
||
Procedure _LstrLAsg(var dest: AnsiString; source: AnsiString) |
复制 Ansi 字符串。但是和 _LstrAsg 的区别不详 |
|||
Procedure _NewAnsiString(length: Longint) |
EAX :长度 |
EAX (指针) |
分配指定长度的 AnsiString |
|
procedure _LStrFromPCharLen(var Dest: AnsiString; Source: PAnsiChar; Length: Integer) |
EAX :目标字符串 EDX :源字符串 ECX :要复制的长度 |
分配并从 PChar 复制指定长度的 AnsiString |
||
procedure _LStrFromPWCharLen(var Dest: AnsiString; Source: PWideChar; Length: Integer) |
EAX :目标字符串 EDX :源字符串 ECX :要复制的长度 |
分配并从 PWideChar 复制指定长度的 AnsiString |
||
procedure _LStrFromChar(var Dest: AnsiString; Source: AnsiChar) |
EAX :目标字符串 EDX :源字符串 |
单字符的分配和复制 |
||
procedure _LStrFromWChar(var Dest: AnsiString; Source: WideChar) |
EAX :目标字符串 EDX :源字符串 |
单字符的分配和复制 |
||
procedure _LStrFromPChar(var Dest: AnsiString; Source: PAnsiChar) |
Pchar 到 AnsiStr 的转换 |
|||
procedure _LStrFromPWChar(var Dest: AnsiString; Source: PWideChar) |
PWideChar 到 AnsiStr 的转换 |
|||
procedure _LStrToString(var Dest: ShortString; const Source: AnsiString; MaxLen: Integer) |
EAX :目标字符串 EDX :源字符串 ECX :要复制的长度 |
AnsiString 到 Pascal 字符串的转换 |
||
Function _LstrLen(str: AnsiString): Longint |
EAX :目标字符串 |
EAX |
AnsiStr 的长度 |
|
Procedure _LstrCat(var dest: AnsiString; source: AnsiString) |
EAX :目标字符串 EDX :源字符串 |
Ansi 字符串的连接 |
dest+=source |
|
Procedure _LStrCat3(var dest:AnsiString; source1: AnsiString; source2: AnsiString) |
EAX :目标字符串 EDX :源字符串 1 ECX :源字符串 2 |
Ansi 字符串的连接 |
dest+=source |
|
Procedure _LstrCatN(var dest:AnsiString; argCnt: Integer; ...) |
EAX :目标字符串 EDX :源字符串的个数 +2 [ESP+4*i] :第 i 个源字符串的指针 |
Ansi 字符串的连接 |
这里的入口参数比较特别 |
|
_LStrCmp |
EAX :左字符串 EDX :右字符串 |
标志位 Z |
Ansi 字符串比较 |
if s=s1 |
_LStrAddRef |
EAX :目标字符串 |
增加 Ansi 字符串的引用计数 |
这个可以不用管 |
|
_LStrToPChar |
EAX |
EAX |
类型转换 |
|
Procedure _LstrCopy(const s : AnsiString; index, count : Integer): AnsiString |
EAX :目标字符串 EDX :起始位置 ECX :要复制的长度 |
[ESP+4] |
复制指定长度的 Ansi 子串 |
|
_LStrDelete |
EAX :目标字符串 EDX :起始位置 ECX :要删除的长度 |
同 Delete |
| |
Procedure _LstrInsert(const source : AnsiString; var s : AnsiString; index : Integer) |
EAX :要插入的字符串 EDX :目标字符串 ECX :要插入的位置 |
将 source 插入到 s 的 index 位置 |
结果是 s 加长 |
|
_LStrPos |
EAX :子串 EDX :目标字符串 |
EAX |
同 POS |
|
_LStrSetLength |
EAX :目标字符串 EDX :新长度 |