📄 hyperstr.pas
字号:
asm
Push ESI
Push EDI //save the important stuff
Xor EBX,EBX
Or EAX,EAX
Jz @Done
Push EAX
Call UniqueString
Pop EAX
Mov ESI,[EAX] //get Source address in read register
Or ESI,ESI
Jz @Done
Mov ECX,[ESI-4] //get length into count register
Jecxz @Done //bail out if zero length
Add ESI,ECX //point to end
Dec ESI
Mov EDI,ESI //...and write register
Mov DL,32 //looking for spaces (or less)
Std //make sure we go backwards
@L1:
Lodsb
Cmp AL,DL //space or less?
Jbe @L2 //yes, then skip the write
Stosb //otherwise, write it back
@L2:
Dec ECX
Jnz @L1
Mov AL,DL
@L3:
Cmp ESI,EDI //read = write ?
Jz @Done //yes, then we're done
Stosb //otherwise, pad with a space
Jmp @L3 //and do it again
@Done:
Cld
Pop EDI //restore the important stuff
Pop ESI
end; //and we're outta here
function DeleteC(var Source:AnsiString;const X:Char):Integer;
{Convert specified char. into right justified spaces which can be
deleted if necessary using RTrim or SetLength.
Returns: Length minus #chars. converted to spaces.}
asm
Push ESI
Push EDI //save the important stuff
Push EBX
Xor EBX,EBX
Or EAX,EAX
Jz @Done //abort if null
Push EAX
Push EDX
Call UniqueString
Pop EDX
Pop EAX
Mov ESI,[EAX] //get address into read register
Or ESI,ESI //check for null pointer
Jz @Done
Mov EDI,ESI //...and write register
Mov ECX,[ESI-4] //get length into count register
Mov EBX,ECX //save it in EBX
Jecxz @Done //bail out if zero length
Mov AH,X //looking for spaces (or less)
Cld //make sure we go forward
@L1:
Lodsb
Cmp AL,AH //equal?
Jz @L2 //yes, then skip the write
Stosb //write it back
@L2:
Dec ECX
Jnz @L1
Mov AL,32 //setup to pad length
@L3:
Cmp ESI,EDI //read = write ?
Jz @Done //yes, then we're done
Stosb //pad with space
Dec EBX //decrease length
Jmp @L3 //and do it again
@Done:
Mov Result,EBX //output length
Pop EBX
Pop EDI //restore the important stuff
Pop ESI
end; //and we're outta here
function DeleteS(var Source:AnsiString;const Index,Count:Integer):Integer;
{Convert Count char. starting at Index into right justified spaces which can
be deleted if necessary using RTrim or SetLength.
Returns: Length minus #chars. converted to spaces.}
asm
Push ESI
Push EDI //save the important stuff
Push EBX
Push EBP
Xor EBP,EBP
Or EAX,EAX
Jz @Done //abort if null
Push ECX
Push EAX
Push EDX
Call UniqueString
Pop EDX
Pop EAX
Pop ECX
Cld //make sure we go forward
Mov ESI,[EAX] //get address into read register
Or ESI,ESI //check for null pointer
Jz @Done
Mov EBP,[ESI-4] //get length into EBP
Or EBP,EBP
Jz @Done //bail out if zero length
Jecxz @Done //abort if zero count
Cmp EBP,EDX
Jb @Done //bail out if too short
Mov EBX,EBP //Move length to EBX
Dec EDX //zero based
Add ESI,EDX //start offset
Mov EDI,ESI //save in write pointer
Sub EBX,EDX //remaining characters
Cmp EBX,ECX
Jbe @L1
Add ESI,ECX
Sub EBX,ECX
// XChg ECX,EBX
Mov EAX,EBX
Mov EBX,ECX
Mov ECX,EAX
Rep movsb
@L1:
Mov AL,32
Sub EBP,EBX
Mov ECX,EBX
Rep stosb
@Done:
Mov EAX,EBP //output length
Pop EBP
Pop EBX
Pop EDI //restore the important stuff
Pop ESI
end; //and we're outta here
function DeleteD(var Source:AnsiString;const X:Char):Integer;
{Convert trailing duplicates of specified char. into right justified spaces
which can be deleted if necessary using RTrim or SetLength. Only duplicates
are affected, the first character in a run of duplicates is left in place.
Returns: Length minus #chars. converted to spaces.}
asm
Push ESI
Push EDI //save the important stuff
Push EBX
Xor EBX,EBX
Or EAX,EAX
Jz @Done //abort if null
Push EAX
Push EDX
Call UniqueString
Pop EDX
Pop EAX
Mov ESI,[EAX] //get address into read register
Or ESI,ESI
Jz @Done
Mov EDI,ESI //...and write register
Mov ECX,[ESI-4] //get length into count register
Mov EBX,ECX //save it in EBX
Jecxz @Done //bail out if zero length
Cld //make sure we go forward
Mov DH,DL //DH will hold the "prior" character
Not DH //make sure "prior" doesn't match on start
@L1:
Lodsb
Cmp AL,DL //equal to target?
Jnz @L2 //no, then write it back
Cmp AL,DH //same as "prior" ?
Jnz @L2 //no, then write it back
Jmp @Skip //a dup --- skip the write
@L2:
Stosb //write it back
@Skip:
Mov DH,AL //save our "prior" character
Dec ECX
Jnz @L1
Mov AL,32 //setup to pad length
@L3:
Cmp ESI,EDI //read = write ?
Jz @Done //yes, then we're done
Stosb //pad with space
Dec EBX //decrease length
Jmp @L3 //and do it again
@Done:
Mov Result,EBX //output length
Pop EBX
Pop EDI //restore the important stuff
Pop ESI
end; //and we're outta here
procedure _TableScanIni;
{Initialization for table scanning routines. Internal use only.}
asm
Or EAX,EAX //zero source ?
Jz @NotFound
Or EDX,EDX //zero table ?
Jz @NotFound
Mov ESI,ECX //save start in ESI, temporarily
Or ECX,ECX
Jz @NotFound //abort if zero start
Jns @L0 //skip if no sign bit
Neg ECX //absolute value of Start
@L0:
Mov EBP,EAX //save Source address
Mov EAX,[EAX-4] //source length
Cmp ECX,EAX //start beyond end ?
Ja @NotFound //yes, then abort
Mov EAX,[EDX-4] //table length
Or EAX,EAX
Jz @NotFound //Abort if zero table
Cmp EAX,256 //abort if Table too long
Ja @NotFound
Cld //insure we go forward
Push EBP //Save Source address
Push ECX //save Start
Push EDX //save Table address
Push EAX //save Table length
Mov ECX,8
Xor EAX,EAX
Lea EDI,iScan //initialize scan array
Push EDI //save the pointer
Rep Stosd //store 8 dbl words (32 bytes)
Pop EDI //restore pointer
Pop ECX //Table length
Lea EBP,RevCase
Shl ECX,1 //move case bit from ESI to ECX
Shl ESI,1
Rcr ECX,1
Pop ESI //Table address
Xor EAX,EAX
@L2:
Lodsb //get a byte from table
Mov EDX,EAX //save it in EDX
And EDX,31 //bit index
Mov DH,AL
Shr EAX,5 //byte index, divide by 32
Shl EAX,2 //multiply by 4 for dbl-word
Mov EBX,[EDI+EAX] //get the dbl-word
Bts EBX,EDX //set the bit
//* Bts EBX,DL //set the bit
Mov [EDI+EAX],EBX //store it back
Bt ECX,31 //case insensitive ?
Jnc @Skip //no, then skip
Shr EDX,8
Mov AL,[EBP+EDX] //reverse case
Mov EDX,EAX //save it in EDX
And EDX,31 //bit index
Shr EAX,5 //byte index, divide by 32
Shl EAX,2 //multiply by 4 for dbl-word
Mov EBX,[EDI+EAX] //get the dbl-word
Bts EBX,EDX //set the bit
Mov [EDI+EAX],EBX //store it back
@Skip:
Dec CX //do it again
Jnz @L2
Pop EAX //get Start
Pop EBP //get Source address
Mov ESI,EBP
Mov ECX,[ESI-4] //Source length
Dec EAX //zero based Start
Add ESI,EAX //adjust Source
Jmp @Done
//returns ESI=Pointer to Start position
// EDI=Pointer to iScan array
// ECX=Full Length Source
// EAX=Zero based Start
// EBP=Pointer to Source[1]
// Direction flag clear
@NotFound:
Xor ECX,ECX
//returns ECX=0 on error
@Done:
end;
function DeleteI(var Source:AnsiString;const Table:AnsiString; const Index:Integer):Integer;
{Convert Table chars. from Index position forward into right justified spaces
which can be deleted if necessary using RTrim or SetLength.
Returns: Valid char. count; length minus chars. converted to spaces.}
asm
Push EBX //save the important stuff
Push ESI
Push EDI
Push EBP
Or EAX,EAX
Jz @Exit
Push EAX
Push EDX
Push ECX
Call UniqueString
Pop ECX
Pop EDX
Pop EAX
Mov EAX,[EAX]
Call _TableScanIni
Jecxz @Abort
Push ECX //save length
Sub ECX,EAX //adjust for Start
Mov EBX,ESI //use EBX as write pointer
Xor EAX,EAX
@Next:
Lodsb //get the byte
Mov DL,AL //save it in DL
Mov DH,DL //and in DH
And DL,31 //bit index
Shr EAX,5 //dbl-word index
Shl EAX,2
Mov EBP,[EDI+EAX] //get the dbl-word
Bt EBP,EDX
//* Bt EBP,DL //test the bit
Jc @Skip //skip write if in Table
Mov [EBX],DH
Inc EBX
@Skip:
Dec ECX
Jnz @Next
Pop EAX //original source length
Mov DH,32 //prepare to space fill
@L3:
Cmp EBX,ESI //read = write ?
Jz @Exit //yes, then we're done
Mov [EBX],DH //no, then space fill
Inc EBX
Dec EAX //adjust output length
Jmp @L3 //and do it again
@Abort:
Xor EAX,EAX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -