用一句简单的程序调试var x:string;begin x:='xxxxxxxxxxxxxxxxxxxxxxxxxxxx';//设定中断调试器会得到这样的结果//Unit2.pas.28: x:='xxxxxxxxxxxxxxxxxxxxxxxxxxxx';0045206F 8D45FC lea eax,[ebp-$04]00452072 BAB4204500 mov edx,$004520b4 //指向字符串的内存指针00452077 E86426FBFF call @LStrLAsg@LStrLAsg的源代码在system单元里面可以找到我搜索了一下这个函数的资料搜索到一篇02年的文章14 楼xzgyb(老达摩)回复于 2002-11-15 17:37:12 得分 25具体看一下 procedure TMainForm.Button1Click(Sender: TObject); var s:string; begin s:='111'; listbox1.Items.Add (inttostr(integer(@s))); listbox1.Items.Add (inttostr(integer(pchar(s)))); listbox1.Items.Add (inttostr(integer(@s[1]))); listbox1.Items.Add (inttostr(integer(pchar(s)))); end; 的汇编码 这里s为局部变量 s := '111'的汇编码 lea eax, [ebp-$04] mov edx, $00464d00 //$00454d00即为'111'在数据段中的地址 call @LStrLAsg 再看看LStrAsg TEST EDX,EDX JE @@sourceDone { bump up the ref count of the source } MOV ECX,[EDX-skew].StrRec.refCnt //这里ECX为$FFFFFFFF INC ECX //所以这时ECX为0,跳到@@SourceDone,没有做下步引用计数加1的运算 JLE @@sourceDone { literal assignment -> jump taken } LOCK INC [EDX-skew].StrRec.refCnt @@sourceDone: { we need to release whatever the dest is pointing to } XCHG EDX,[EAX] { fetch str } //这步EAX存的就是'111'在数据段的地址,而 EDX为0 TEST EDX,EDX { if nil, nothing to do } JE @@done //返回 MOV ECX,[EDX-skew].StrRec.refCnt { fetch refCnt } DEC ECX { if < 0: literal str } JL @@done LOCK DEC [EDX-skew].StrRec.refCnt { threadsafe dec refCount } JNE @@done LEA EAX,[EDX-skew].StrRec.refCnt { if refCnt now zero, deallocate} CALL _FreeMem @@done: 此时s中存的是'111'在数据段的地址 而调用@s[1] lea eax, [ebp-$04] call @UniqueStringA UniqueStringA判断引用计数减1如果不等于零的话就调用NewAnsiString重新 分配一段内存,这时的引用计数就为1 同样的 s = '111' s如果为局部变量,s返回的是'111'在数据段的地址,它的引用计数为-1 s如果为全局变量,这句会调用_LStrAsg,_LStrAsg又调用NewAnsiString,所以 对全局变量s,的引用计数为1 s := ''; s := s + '111' 对于 s := ''; 汇编码如下 lea eax, [ebp-$04] call @LStrClr 而eax内容为0,@LStrClr什么也不做 s := s + '111'的汇编码 lea eax, [ebp-$04] mov edx, $00464d08 call @LStrCat 而LStrCat判断eax内容如为0就调用LStrAsg,这样在调用NewAnsiString 则产生一个引用计数为1的串 就是这样