Seite 2 von 2

Verfasst: 29.07.2007 23:44
von PureLust
Kiffi hat geschrieben:
Kaeru Gaman hat geschrieben:dz... wieder mal was wo PB nicht "regelkonform" ist... dz dz dz
in welcher Sprache wird eine For-Next-Schleife denn mindestens 1mal
durchlaufen? Ich zumindest kenne keine.
@Kaeru: Könnte es sein, dass Du das mit einer Repeat/Until-Schleife verwechselt hast?
Denn bei dieser ist es naturbedingt, dass sie zumindest einmal durchlaufen wird.

@coMstructor:
Danke für den Link und die toll gemachte ASM- bzw. Compilerbau Lern-Seite.
Werde ich mich mal drüber her machen und mein Glück damit versuchen. :allright:

(PS: Bei dem Versuch die von Dir verlinkte "Anfänger"-Seite über die Seitennavigation wieder zu finden bin ich ja fast verzweifelt.
Unter der Link-Bezeichnung "Buch" hätte ich's als letztes vermutet, da ich darunter Werbung zu einem Buch erwartet habe.
Vielleicht wäre hier eine Bezeichnung wie "Themenübersicht" eine besser Wahl.
Dennoch, tolle und leerreiche Seite. :allright: )

Verfasst: 29.07.2007 23:48
von Kaeru Gaman
hm... nein, verwechselt hab ichs garantiert nicht...

also, ich bin mir jetzt nicht sicher, wie das in QBasic war (anfang der 90er),
aber ich könnte schwören, dass im Commodore-Basic aufm C64 genau das eine wichtige lektion war,
zu lernen, dass auch eine falsch angelegte For/Next wenigstens 1x durchlaufen wurde....

wisst ihr, manchmal stellt man uralte erfahrungen erst dann in frage,
wenn die richtige frage gestellt wird.... xD

Verfasst: 30.07.2007 03:39
von Olaf
Also mittlerweile neige ich dazu fast alles, was grade so machbar und mit angemessenem Aufwand bewältigbar is, in ASM zu machen. So hab ich mal ne kleine passwortlose Ver- und Entschlüsselungsroutine gebastelt und einmal in Rein-PB bzw. einmal in Rein-ASM geschrieben. Nun hat die ASM-Routine für das Verschlüsseln von 200MB Speicher ca. 1 Sekunde benötigt auf meinem 1,8 GHz Sempron-Mobile, während der Rein-PB-Code über ne halbe Minute benötigte.

Code: Alles auswählen

;InternalXOr-Encoding
;Prozessortypen: x386 und höher (verwendet nicht: MMX, SSE, SSE2, SSE3)

Global progress.l

Procedure InternalEnXOr(*MemoryID,Length.l)
  ;Die gegenüber dem anderen Assemblercode eingerückten Zeilen beziehen sich nur auf
  ;die Aktualisierung der globalen fortschrittsanzeigenden Variablen, die dann von einem
  ;den Vorgang überwachenden Thread genutzt werden können, um mit Hilfe der Gesamtlänge
  ;und der Fortschrittsvariablen eine Fortschrittsanzeige zu ermöglichen.
  ;Diese Zeilen sind für eine nicht überwachte Verschlüsselung nicht notwendig und können dann
  ;auskommentiert werden.
  !MOV dword eax,[p.v_Length]   ;Length in EAX laden
  !CMP eax,2                    ;EAX mit 2 vergleichen
  !JL  TooShort_En              ;Falls EAX (=Length) kürzer als 2, zu TooShort_En springen
  
  !MOV dword ecx,[p.p_MemoryID] ;Speicheranfangsadresse in ECX speichern
  !MOV dword ebx,0              ;Als Positionszeiger EBX verwenden und auf 0 setzen
  !INC dword ebx                ;Leseposition um 1 erhöhen
  
  !NextEnXOrStep:               ;Schleifen-Sprungmarke
  
  !MOV al,[ecx+ebx]             ;Wert an der Speicherstelle [ECX+EBX] in AL laden
  !MOV ah,[ecx+ebx-1]           ;Wert an der Speicherstelle [ECX+EBX-1] in AH laden
  !XOR al,ah                    ;AL mit AH durch XOr verknüpfen und Ergrbnis in AL speichern
  !MOV [ecx+ebx],al             ;neuen Wert von AL an die Stelle [ECX+EBX] zurückschreiben
  
  !INC dword ebx                ;Leseposition EBX um 1 erhöhen
    !MOV dword [v_progress],ebx   ;Leseposition EBX in der globalen Variable für die Fortschrittsanzeige speichern
  !CMP dword ebx,[p.v_Length]   ;Leseposition EBX und Speicherlänge vergleichen
  !JNE NextEnXOrStep            ;Falls nicht gleich (also noch nicht am Ende angekommen), zu NextEnXOrStep zurückspringen
  
  !MOV eax,[p.v_Length]         ;ProcedureReturn den Wert von Length übergeben
  ProcedureReturn
  
  !TooShort_En:                 ;Länge war leider zu kurz:
  !MOV eax,0                    ;ProcedureReturn den Wert 0 (=fehlgeschlagen) übergeben
  ProcedureReturn
EndProcedure

Procedure InternalDeXOr(*MemoryID,Length.l)
  ;Die gegenüber dem anderen Assemblercode eingerückten Zeilen beziehen sich nur auf
  ;die Aktualisierung der globalen fortschrittsanzeigenden Variablen, die dann von einem
  ;den Vorgang überwachenden Thread genutzt werden können, um mit Hilfe der Gesamtlänge
  ;und der Fortschrittsvariablen eine Fortschrittsanzeige zu ermöglichen.
  ;Diese Zeilen sind für eine nicht überwachte Verschlüsselung nicht notwendig und können dann
  ;auskommentiert werden.
  !MOV dword eax,[p.v_Length]   ;Length in EAX laden
  !CMP eax,2                    ;EAX mit 2 vergleichen
  !JL  TooShort_De              ;Falls EAX (=Length) kürzer als 2, zu TooShort_De springen
  
  !MOV dword ecx,[p.p_MemoryID] ;Speicheranfangsadresse in ECX speichern
  !MOV dword ebx,[p.v_Length]   ;Als Positionszeiger EBX verwenden und auf Length setzen
  !DEC dword ebx                ;Leseposition EBX um 1 verringern (letztes Zeichen steht nicht an der Stelle Length, sondern bei Length-1)
  
  !NextDeXOrStep:               ;Schleifen-Sprungmarke
  
  !MOV al,[ecx+ebx]             ;Wert an der Speicherstelle [ECX+EBX] in AL laden
  !MOV ah,[ecx+ebx-1]           ;Wert an der Speicherstelle [ECX+EBX-1] in AH laden
  !XOR al,ah                    ;AL mit AH durch XOr verknüpfen und Ergrbnis in AL speichern
  !MOV [ecx+ebx],al             ;neuen Wert von AL an die Stelle [ECX+EBX] zurückschreiben
  
  !DEC dword ebx                ;Leseposition EBX um 1 verringern
    !MOV dword eax,[p.v_Length]   ;Länge in EAX speichern...
    !SUB dword eax,ebx            ;...und Leseposition EBX von EAX subtrahieren, um Anzahl der bereits berechneten Zeichen zu erhalten
    !MOV [v_progress],eax         ;diese dann in der fortschrittsanzeigenden Variablen speichern
  !CMP dword ebx,0              ;Leseposition EBX mit 0 vergleichen
  !JA  NextDeXOrStep            ;Falls größer 0(also noch nicht am Ende angekommen) zu NextDeXOrStep zurückspringen
  
  !MOV eax,[p.v_Length]         ;ProcedureReturn den Wert von Length übergeben
  ProcedureReturn
  
  !TooShort_De:                 ;Länge war leider zu kurz:
  !MOV eax,0                    ;ProcedureReturn den Wert 0 (=fehlgeschlagen) übergeben
EndProcedure

Size=200*1024*1024
*mem=AllocateMemory(Size)
Debug "Allocated"
Start=ElapsedMilliseconds()
InternalEnXOr(*mem,Size)
Time=ElapsedMilliseconds()-Start
Debug Time
Debug "EnXOred"
Start=ElapsedMilliseconds()
InternalDeXOr(*mem,Size)
Time=ElapsedMilliseconds()-Start
Debug Time
Debug "DeXOred"
war somit viel schneller als

Code: Alles auswählen

Procedure InternalEnXOr(*MemoryID,Length)
  If Length>1
    TempByte.b=PeekB(*MemoryID)
    For pos=1 To Length -1
      TempByte=PeekB(*MemoryID+pos)!TempByte
      PokeB(*MemoryID+pos,TempByte)
    Next pos
  EndIf
EndProcedure

Procedure InternalDeXOr(*MemoryID,Length)
  If Length>1
    For pos=Length-1 To 1 Step -1
      PokeB(*MemoryID+pos,PeekB(*MemoryID+pos)!PeekB(*MemoryID+pos-1))
    Next pos
  EndIf
EndProcedure

Size=200*1024*1024
*mem=AllocateMemory(Size)
Debug "Allocated"
Start=ElapsedMilliseconds()
InternalEnXOr(*mem,Size)
Time=ElapsedMilliseconds()-Start
Debug Time
Debug "EnXOred"
Start=ElapsedMilliseconds()
InternalDeXOr(*mem,Size)
Time=ElapsedMilliseconds()-Start
Debug Time
Ob daran jedoch jetzt nur die Schleifen oder auch vllt. die Peek/Poke-Befehle dran Schuld sind, weiß ich nicht, da ich das noch nicht speziell getestet hab.

Verfasst: 30.07.2007 21:09
von Thorium
Das ist meine Implementierung von XOr-Verschlüsslung:

Code: Alles auswählen

Procedure CryptXor(sData.l, DataSize.l, Key.b)

  !mov ecx,[p.v_DataSize]
  !mov esi,[p.v_sData]
  !mov bl,[p.v_Key]
  
  !CryptLoop:
    !mov al,[esi]
    !xor al,bl
    !mov [esi],al
    !inc bl
    !inc esi
    !dec ecx
    !jecxz CryptLoopEnd
    !jmp CryptLoop
  !CryptLoopEnd:
  
EndProcedure
Es gibt auch einen Loop-Befehl in Assembler aber den sollte man besser nicht verwenden da langsam.

Verfasst: 30.07.2007 21:48
von Olaf
Außerdem benutzt Loop noch das ECX-Register, was ich nicht mag, da ich's dann nicht zusäztlich noch verwenden kann...