Espero que alguém com habilidades em assembler possa criar uma função Delphi para mim que ignore o primeiro caractere de qualquer string se ela começar com Chr(127). Isso é usado em uma comparação de classificação, que é extremamente lenta com 30.000 itens, quando é preciso copiar o texto do segundo caractere antes da comparação. Esta é a função original.
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 ESI
end;
Muito obrigado se você puder ajudar.
Eu certamente entendo como "ter que copiar o texto do segundo caractere antes da comparação" pode ser extremamente lento.
Você não precisa copiar nada. Na presença de Chr(127), você considera apenas a segunda posição na string como seu verdadeiro início. Em código, isso significa incrementar os endereços ESI/EDI e também decrementar os comprimentos EAX/EDX.
Para um melhor desempenho, não use BL e BH, mas use registradores completos de 32 bits, mesmo que isso signifique preservar um registrador extra como EBP.
Tenho certeza de que o loop e especialmente sua parte LCase poderiam ser mais otimizados, mas acho que o problema principal sobre ignorar um Chr(127) inicial foi resolvido...
Há um pequeno problema algorítmico
Seu loop principal (
@@3
) tem essencialmente duas partes: uma que faz uma comparação "como está" (cmpsb
) e outra que faz uma comparação "sem distinção entre maiúsculas e minúsculas". O problema é que esta última faria sentido se fosse a única parte do loop, mas, combinada com a primeira parte, só deve ser usada para bytes atuais que sejam confirmados como alfabéticos .Não sei se alguma de suas sequências de caracteres incluirá um código ASCII no intervalo de 91 a 96, mas se for esse o caso, atualmente é possível que seu código original informe incorretamente sobre uma comparação entre qualquer um de [a,z] e qualquer um de ]Z,a[ devido à ocorrência do UCase e, da mesma forma, meu primeiro código pode informar incorretamente sobre uma comparação entre qualquer um de [A,Z] e qualquer um de ]Z,a[ devido à ocorrência do LCase.
Este é um código revisado:
Aliás, o novo código deve rodar mais rápido agora que apliquei a técnica que Peter mencionou em um comentário .