Re: Optimiert(est)er peek für einen unsigned long 32bit
Verfasst: 03.09.2013 00:10
So wie ich das verstehe, werden bei Base85 aus 4Bytes -> 5Bytes gemacht.
Dabei wird die 256er-Basis in eine 85er-Basis zerlegt.
Der ASM-Befehl DIV ist dafür natürlich optimal geeignet, weil er sowohl dividiert, als auch den Rest ausgibt.
Das heißt, eine LONG (4Bytes) in EAX werfen, fünf mal DIV 85 anwenden und die Reste jeweils auf die Zeichen im String addieren, der vorher aus "!" besteht.
Hier ist mal mein Code (x86 only):
Läuft bei 10MB trotz Debugger recht flott durch und gibt mir auch laut WIKI das richtige Ergebnis für "Man sure" zurück: "9jqo^F*2M7"
Hinweis: Der ASM-Code ist nicht ganz sauber, da ich die Register ebx und esi nicht sichere. Das müsste ggf. noch nachgetragen werden. Außerdem sind nur 4er-Längen erlaubt!
Dabei wird die 256er-Basis in eine 85er-Basis zerlegt.
Der ASM-Befehl DIV ist dafür natürlich optimal geeignet, weil er sowohl dividiert, als auch den Rest ausgibt.
Das heißt, eine LONG (4Bytes) in EAX werfen, fünf mal DIV 85 anwenden und die Reste jeweils auf die Zeichen im String addieren, der vorher aus "!" besteht.
Hier ist mal mein Code (x86 only):
Code: Alles auswählen
Procedure.s Base85Encoder(*Input, Length.i)
Protected Result.s = RSet("", Length*5/4, "!")
*Input + Length
!MOV ebx, 85 ; Divisor
!MOV ecx, [p.p_Input] ; Leseadresse
!MOV edi, [p.v_Result] ; Schreibadresse
!SUB ecx, [p.v_Length]
!base85_loop:
!MOV eax, [ecx] ; Tiefer Dividend-Teil
!BSWAP eax
!MOV edx, 0 ; Hoher Dividend-Teil = 0
!DIV ebx ; Erste Division
!ADD [edi+4], dl ; Rest (nur das tiefste Byte) kommt in den String, addiert auf das "!"
!MOV edx, 0
!DIV ebx ; Zweite Division
!ADD [edi+3], dl
!MOV edx, 0
!DIV ebx ; Dritte Division
!ADD [edi+2], dl
!MOV edx, 0
!DIV ebx ; Vierte Division
!ADD [edi+1], dl
!MOV edx, 0
!DIV ebx ; Fünfte Division
!ADD [edi+0], dl
!ADD ecx, 4 ; Leseadresse + 4
!ADD edi, 5 ; Schreibadresse + 5
!CMP ecx, [p.p_Input] ; Fertig?
!JNZ base85_loop
ProcedureReturn Result
EndProcedure
Define *Buffer1 = AllocateMemory(9)
PokeS(*Buffer1, "Man sure")
Debug Base85Encoder(*Buffer1, 8)
Define *Buffer2 = AllocateMemory(1024*1024*10)
RandomData(*Buffer2, MemorySize(*Buffer2))
Define String.s = Base85Encoder(*Buffer2, MemorySize(*Buffer2))
Debug String
Debug "Länge: "+Str(Len(String))
Hinweis: Der ASM-Code ist nicht ganz sauber, da ich die Register ebx und esi nicht sichere. Das müsste ggf. noch nachgetragen werden. Außerdem sind nur 4er-Längen erlaubt!