两个字符串比较函数的评估(仅比较是否相同,忽略大小写)
两个使用汇编实现的忽略大小写的仅比较是否相同的字符串比较函数,如果是在实际应用当中使用,都会选择哪一个,为什么?这里假定两字符串长度相同(实际应用当中还有前一级函数处理长度问题)
一般地比较
- Delphi(Pascal) code
function IsSameText(const Str1, Str2: PChar; Len: Cardinal): Boolean; assembler;asm PUSH EDI PUSH ESI PUSH EBX MOV ESI,EAX //Str1 MOV EDI,EDX //Str2 MOV EBX,ECX //Len XOR EAX,EAX OR ECX,ECX JE @@T REPNE SCASB //扫描ESI/EDI指针指向的字符,当不相等的时候结束,否则扣减ECX计数,直到计数为0结束 SUB EBX,ECX MOV ECX,EBX MOV EDI,EDX XOR EDX,EDX@@1: REPE CMPSB JE @@T MOV AL,[ESI-1] //AL = Str1[Index] CMP AL,'a' JB @@2 CMP AL,'z' JA @@2 SUB AL,20H //To Upper@@2: MOV DL,[EDI-1] //DL = Str2[Index] CMP DL,'a' JB @@3 CMP DL,'z' JA @@3 SUB DL,20H //To Upper@@3: SUB AL,DL JE @@1 //AL - DL = 0? NextChar:End (return False)@@F: xor EAX,EAX //False,EAX return 0 jmp @@E@@T: mov EAX,1 //True,EAX return 1@@E: POP EBX POP ESI POP EDIend;
应用查表(实际上这个查表也可以应用于大小写转换)
- Delphi(Pascal) code
function IsSameText(const Str1, Str2: PChar; Len: Cardinal): Boolean; assembler;asm PUSH EDI PUSH ESI PUSH EBX MOV ESI,EAX //Str1 MOV EDI,EDX //Str2 MOV EBX,ECX //Len XOR EAX,EAX OR ECX,ECX JE @@T REPNE SCASB //扫描ESI/EDI指针指向的字符,当不相等的时候结束,否则扣减ECX计数,直到计数为0结束 SUB EBX,ECX MOV ECX,EBX MOV EDI,EDX XOR EDX,EDX LEA EBX,CS:[OFFSET @LOWER]@@1: REPE CMPSB JE @@T MOV AL,[ESI-1] //AL = Str1[Index] MOV AL,[EBX + EAX] //AL = Lower[Ord(AL)]@@2: MOV DL,[EDI-1] //DL = Str2[Index] MOV DL,[EBX + EDX] //DL = Lower[Ord(DL)]@@3: SUB AL,DL //AL = AL - DL JE @@1 //AL = 0? NextChar: End (return false)@@F: xor EAX,EAX jmp @@E@@T: mov EAX,1@@E: POP EBX POP ESI POP EDI RET@LOWER: DB 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h, 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh DB 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h, 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh DB 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h, 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh DB 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h, 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh DB 040h //大写字母 //--------------------- (*DB 041h, 042h, 043h, 044h, 045h, 046h, 047h, 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh DB 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h, 058h, 059h, 05ah*) //===================== //小写字母 //--------------------- DB 061h, 062h, 063h, 064h, 065h, 066h, 067h, 068h, 069h, 06ah, 06bh, 06ch, 06dh, 06eh, 06fh DB 070h, 071h, 072h, 073h, 074h, 075h, 076h, 077h, 078h, 079h, 07ah //===================== DB 05bh, 05ch, 05dh, 05eh, 05fh DB 060h //--------------------- //小写字母 DB 061h, 062h, 063h, 064h, 065h, 066h, 067h, 068h, 069h, 06ah, 06bh, 06ch, 06dh, 06eh, 06fh DB 070h, 071h, 072h, 073h, 074h, 075h, 076h, 077h, 078h, 079h, 07ah //====================== DB 07bh, 07ch, 07dh, 07eh, 07fh DB 080h, 081h, 082h, 083h, 084h, 085h, 086h, 087h, 088h, 089h, 08ah, 08bh, 08ch, 08dh, 08eh, 08fh DB 090h, 091h, 092h, 093h, 094h, 095h, 096h, 097h, 098h, 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh DB 0a0h, 0a1h, 0a2h, 0a3h, 0a4h, 0a5h, 0a6h, 0a7h, 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh DB 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h, 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh DB 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h, 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh DB 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h, 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh DB 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h, 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh DB 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h, 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffhend;
[解决办法]
我觉得第一种方法好
它直接操作的是存储地址 基本上没有多余的东西
第二种方法里 有一个查表的过程 这样的话 时间复杂度会大点
向僵哥 学习
[解决办法]
就是这个
CMP AL,'a'
JB @@2
CMP AL,'z'
JA @@2
SUB AL,20H //To Upper
和这个
MOV AL,[EBX + EAX] //AL = Lower[Ord(AL)]
的效率问题吧。
速度的话,我想间接寻址应该比三次减法运算要快吧。不过目标字符串都是大写的话就只用一次减法运算了。
[解决办法]
@_@
[解决办法]
300分吓人啊
[解决办法]
不错。
[解决办法]
字少的前面快,字多的后面快,前一种跟delphi的差不多
[解决办法]
占位,学习
[解决办法]
查表有效率,和CRC32算法差不多,但是相应的,程序就会大一些,反之亦然
CRC32的查表法和直接计算法之间的关系和僵哥的这两个方法都是差不多的
[解决办法]
学习
[解决办法]
[解决办法]
弄个用例测一下就好了
[解决办法]
顶
[解决办法]
看不懂汇编。
如果我自己写的话,大概就是这样:
const
CharsTable: array [Char] of Char;
initChars;
for I := #0 to #$FF do
CharsTable[i] := i;
sametext do:
for I := 0 to len - 1 do
[
result := CharsTable[Src[I]] = CharsTable[Dest[I]];
if not result then break;
]
估计是趋于第二种,如果是第一种,我会直接用CompareMem
[解决办法]
o_o
[解决办法]
MARK,学习
[解决办法]
哪个效率最快呢???
[解决办法]
这2段东西,无论从速度,空间上来看,都差不多,就速度而言,本来我还准备翻翻资料看看指令执行周期来计算一下,可楼主还提到流水线断流的问题,我也就放弃了。(那位仁兄有心可以在不考虑流水线问题先给一个执行指令周期来看看)。这个断流的问题加进来太麻烦了,就第一段代码而言,出现断流的情况无非是,数字,大写,其他字符,在一般情况下,小写英文出现的几率应该比较多吧,当然如果是中文,跳转就比较多了,但每次跳转的时候又有3条指令不会去执行,问题是对于你用的cpu来说流水线有几级?4级,5级,还是更多。所以我认为这样是没有办法计算的。这只能是估计了,大概,也许,可能,第二段代码在多数情况下会运算快一点吧。可是能快多少,我恐怕到了几十兆也就毫秒的差别吧,要是再大的话,让用户等上2个小时和等上3个小时对用户来说也没有多大区别了,还不如配一块高点的cpu。
另外从空间上来说,如果真要考虑的话,大概要回到386年代了,这样的话速度上也就没有什么流水线问题了,一个破386就不要指望几十,几百兆的字符对比了吧。
当然,如果让我选,我就一般应用而言,2个都不选,因为这样的话,以后要修改的话,不太熟悉汇编的人不好改动程序。
ps:楼主大概把程序的中文注释拷错地方了吧 :)
[解决办法]
if str1 =str2 then ....
一群高手闲得没事做
鉴定完毕
[解决办法]
学习学习....!
[解决办法]
D 不是自己有嘛?
[解决办法]
看了一大堆的汇编
弄的有点稀里糊涂的
看来要回去好好的补习以下汇编
根据楼主的多方面考虑
我个人觉得看需要的是速度还是稳定性了
[解决办法]
学习
[解决办法]
学习 顶
[解决办法]
顶
[解决办法]
求怜不如思进取
[解决办法]
我的天呀,这样也行
[解决办法]
[解决办法]
学习
[解决办法]
只要能够随机访问,浪费点内存没事
[解决办法]
向僵哥学习了
[解决办法]
- Delphi(Pascal) code
function CompareText(const S1, S2: string): Integer; assembler;asm PUSH ESI PUSH EDI PUSH EBX MOV ESI,EAX MOV EDI,EDX OR EAX,EAX JE @@0 MOV EAX,[EAX-4]@@0: OR EDX,EDX JE @@1 MOV EDX,[EDX-4]@@1: 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 POP EBX POP EDI POP ESIend;
[解决办法]
好帖子啊,顶一个
[解决办法]
[解决办法]
先顶下,以后研究
[解决办法]
逆向一下别人现成的实现
然后根据需要改一改
[解决办法]
逆向Delphi的实现
[解决办法]
不是搞Delphi的,看不懂,学习。。。
[解决办法]
学习下~!!
[解决办法]
瞻仰高人!
[解决办法]
看看FastCode里面貌似有类似的函数代码