Delphi汇编实现ASCII字符串比较:需忽略首字符(Chr(127))优化排序性能
定制Delphi汇编字符串比较函数(忽略首字符为Chr(127)的情况)
针对你提到的排序性能问题——因复制子串调用原CompareText导致3万条数据排序效率低下,下面直接修改汇编代码,在比较逻辑里直接处理首字符为Chr(127)的情况,无需复制子串:
function CompareCustomText(const S1, S2: string): Integer; assembler; asm PUSH ESI PUSH EDI PUSH EBX // 处理S1:若首字符是127则跳过 MOV ESI, EAX OR ESI, ESI JE @@S1Empty CMP BYTE PTR [ESI], 127 JNE @@S1Skip INC ESI // 指针后移,跳过首字符 DEC DWORD PTR [ESI-4] // 临时减少字符串长度(Delphi字符串前缀是长度值) @@S1Skip: MOV EAX, [ESI-4] // 获取S1处理后的有效长度 @@S1Empty: // 处理S2:逻辑同S1 MOV EDI, EDX OR EDI, EDI JE @@S2Empty CMP BYTE PTR [EDI], 127 JNE @@S2Skip INC EDI // 跳过首字符127 DEC DWORD PTR [EDI-4] // 临时减少长度 @@S2Skip: MOV EDX, [EDI-4] // 获取S2处理后的有效长度 @@S2Empty: // 原CompareText的核心大小写不敏感比较逻辑,完全复用 MOV ECX, EAX CMP ECX, EDX JBE @@2 MOV ECX, EDX @@2: CMP ECX, ECX @@3: REPE CMPSB JE @@6 MOV BL, BYTE PTR [ESI-1] CMP BL, 'a' JB @@4 CMP BL, 'z' JA @@4 SUB BL, 20H @@4: MOV BH, BYTE PTR [EDI-1] CMP BH, 'a' JB @@5 CMP BH, 'z' JA @@5 SUB BH, 20H @@5: CMP BL, BH JE @@3 MOVZX EAX, BL MOVZX EDX, BH @@6: SUB EAX, EDX // 还原原字符串的长度(因为参数是const,不能修改原字符串) MOV ESI, [ESP+12] // 取出原S1的地址 OR ESI, ESI JE @@RestoreS2 CMP BYTE PTR [ESI], 127 JNE @@RestoreS2 INC DWORD PTR [ESI-4] // 把临时减少的长度加回去 @@RestoreS2: MOV EDI, [ESP+16] // 取出原S2的地址 OR EDI, EDI JE @@Exit CMP BYTE PTR [EDI], 127 JNE @@Exit INC DWORD PTR [EDI-4] // 还原S2的长度 @@Exit: POP EBX POP EDI POP ESI end;
关键修改说明
- 首字符跳过逻辑:分别对S1和S2检查首字节是否为127,若是则直接移动指针跳过该字符,同时临时调整字符串长度(Delphi短字符串的前缀4字节是长度值)
- 原字符串保护:因为参数是
const string,不能修改原字符串的长度,所以在比较完成后必须把临时修改的长度还原,避免破坏原字符串结构 - 复用核心逻辑:保留原
CompareText的大小写不敏感ASCII比较逻辑,保证比较行为和原函数一致
性能优势
全程不需要复制子串,直接在原字符串指针上调整后进行比较,彻底消除子串复制带来的内存分配、拷贝开销,3万条数据排序时的性能会明显提升。
内容的提问来源于stack exchange,提问作者Ross
相关产品推荐
相关产品推荐

