一个汇编问题(世界上最快的字符替换函数)(100分)

  • 主题发起人 主题发起人 DreamTiger
  • 开始时间 开始时间
D

DreamTiger

Unregistered / Unconfirmed
GUEST, unregistred user!
因为是从网上下载的一个快速替换的函数,里面用的是Object Pascal和汇编,
所以就贴到这里了。

我的问题是:下面这段程序号称是世界上最快的字符替换函数中的一段查找函
数(的确,它的替换速度比Delphi自带的快10000倍,呵呵)。但是,它对于
中文的支持很不好,主要是因为它在把大写字符变成小写字符的时候,对于中
文字符也进行了改动,这样就导致中文匹配的时候出错。我本想在大小写转换
之前先进行判断该字符是否大于128,是的话,就忽略,不替换。但是它这里
的EAX,EBX,ECX,EDX都用掉了,我对汇编也不熟,不知道应该怎么改动了,哪
位大侠出手救我出水火?(要求不能在这个函数之外先做Lowercase,否则就
没意义了)

//This routine is an identical copy of FastPOS except where commented! The ide
//a is that when grabbing bytes, it ANDs them with $df, effectively making the
//m lowercase before comparing. Maybe this would be quicker if aFindString was
// made lowercase in one fell swoop at the beginning of the function, saving a
//n AND instruction each time.
function FastPosNoCase(
const aSourceString, aFindString : String;
const aSourceLen, aFindLen, StartPos : integer
) : integer;
var
SourceLen : integer;
begin
SourceLen := aSourceLen;
SourceLen := SourceLen - aFindLen;
if (StartPos-1) > SourceLen then begin
Result := 0;
Exit;
end;
SourceLen := SourceLen - StartPos;
SourceLen := SourceLen +2;
asm
push ESI
push EDI
push EBX
mov EDI, aSourceString
add EDI, StartPos
Dec EDI
mov ESI, aFindString
mov ECX, SourceLen
Mov Al, [ESI]
// Make Al lowercase.
and Al, $df
@ScaSB:
Mov Ah, [EDI]
// Make Ah lowercase.
and Ah, $df
cmp Ah,Al
jne @NextChar
@CompareStrings:
mov EBX, aFindLen
dec EBX

//add by ShengQuanhu
Jz @EndOfMatch
//add end

@CompareNext:
mov Al, [ESI+EBX]
mov Ah, [EDI+EBX]
// Make Al and Ah lowercase.
and Al, $df
and Ah, $df
cmp Al, Ah
Jz @Matches
Mov Al, [ESI]
// Make Al lowercase.
and Al, $df
Jmp @NextChar
@Matches:
Dec EBX
Jnz @CompareNext

//add by Shengquanhu
@EndOfMatch:
//add end

mov EAX, EDI
sub EAX, aSourceString
inc EAX
mov Result, EAX
jmp @TheEnd
@NextChar:
Inc EDI
dec ECX
jnz @ScaSB
mov Result,0
@TheEnd:
pop EBX
pop EDI
pop ESI
end;
end;

 
//EAX,EBX,ECX,EDX都用掉了
PUSH呀
 
用test al, $80
test和and是基本相同的,不过不破坏原数.
 
对呀, push, 就可以用了,用完以后 pop,
懒得看了。
 
wrench,SuperMMX:我说的都用掉了不是指在函数外边用掉了,而是在这个函数内部
用掉了,所以Push、POP都是没有用的。
delphi:我用 test al, $80
jl @nextstep
的确达到了目的,但令我百思不得其解的是我用
cmp al, $80
jl @nextstep
或者
cmp al, $80
jp @nextstep
都达不到目的?
 
呵呵,对 汇编懂得少吧,
push pop 是对寄存器来说的,
比如, 你下面要用到 ax, 而 以后还要用就可以 :
push ax
... //用完了
pop ax
... 原来的值。

2, 好象 jl 判断无符号数?有符号数?
忘了,应该是这个问题,
test 检测某些位是否为 1。
 
supermmx:
呵呵,对汇编只懂一点点。
不过,在这个函数中,AX的al,ah用于从两个字符串取要比较的字符,
BX用于纪录aFindString还有多少个字符没有比较,
CX用于纪录aSourceString还有多少个字符没有比较,
这些寄存器我都不能用了,到的确是漏看了DX,呵呵。
为了效率问题,在这里我不可能要用到AX就PUSH,用完了再POP,那样速度
太慢了。其实还是因为不懂汇编,cmp命令都用不好,test命令也不知道。

>好象 jl 判断无符号数?有符号数?
这个是什么意思?
 
1, 就找不用的,实在不行,只好用push, pop ,
2, 牵扯到一个有符号数, 无符号数的 比较跳转问题,
有符号数最高位表示符号,0__+ 1__-,
比较以后,跳转有两套指令,一般不能混用,
要不然会错的,

test 就不说了,

这些是汇编中的基本知识,我用的时候也得看书,记不住。呵呵
 
>我用 test al, $80
> jl @nextstep
>的确达到了目的,但令我百思不得其解的是我用
> cmp al, $80
> jl @nextstep
>或者
> cmp al, $80
> jp @nextstep
>都达不到目的?
test和cmp的原理不同,
test相当于and;cmp相当于sub
即,操作相同不过不保存运算结果
因此,大概应该这样用:
test al, $80
jl @nextstep
或:
cmp al,$80
jz(jnz) al,$80
我也没看几天汇编,瞎说的,别见笑
 
DreamTiger,你所说的"快速替换"应该是"快速查找"吧?
 
beta:这个函数是快速替换的一部分。
 
原来如此,hehe.
 
修正完重贴一编,还有好多人不懂 ASM呢,我替他们谢过你们了。
确实只是POS,要不要改成REPLACE?
 
>修正完重贴一编
赞成
>要不要改成REPLACE
 
这是一定的,我只是想先搞懂这么一个简单的问题:(没找到汇编书)
cmp al, $80 以后,
j?? @nextstep
应该填写什么才能实现当al > $80时跳转到nextstep。
jl,jg好像都不对。
 
应该是jg(jump if greater than ...)那就试一试jnle
 
beta,这两个我都试过,真是奇怪。
 
jnle也试过了,不行?(当然它等于jg)
那可就奇怪了,只好请高手看看啦
 
那将试试ja呗
 

Similar threads

I
回复
0
查看
711
import
I
I
回复
0
查看
670
import
I
I
回复
0
查看
739
import
I
I
回复
0
查看
805
import
I
I
回复
0
查看
647
import
I
后退
顶部