Assembler Hilfe-Thread

  • Zitat von Threadersteller Sprenger120

    Hi,

    Um den ASM Thread ein bisschen zu schonen mache ich hier mal einen Hilfe - Antwort Thread auf.
    Vorrab habe ich aber selber noch ne Frage. Kann man in ASM Arrays ohne viel schreiberei (dauerndes POP und Pushen) verwenden ?

    ________________________________________________________________________________

    Wie wäre es mit einfachen verschlüsselungsalgorithmen?
    Afaik haben neuere Intel-CPUs auch AES eingebaut. Wie man die Funktion benutzt wäre auch mal intressant zu sehen.


    Lieber doch nicht...bestimmt wurden einige schon von dem REPNE SCASD-Monster im 2. Beispiel abgeschreckt....


    Wie sehen denn "einfache" Schleifen aus?

    2 Mal editiert, zuletzt von BugFix (24. August 2010 um 19:43)

  • Zitat

    Wie sehen denn "einfache" Schleifen aus?

    Da gibt es mehrere Möglickeiten. Die einfachste ist der LOOP. Man lädt die Anzahl der Schleifendurchläufe in das ECX-Register und jedes Mal, wenn der LOOP ausgeführt wird, erniedrigt sich der Wert von ECX um eins.
    Also äquivalent zu:

    [autoit]

    $EAX=0
    For $ECX=33 to 0 step -1
    $EAX=$EAX+3
    next

    [/autoit][autoit]

    FasmAdd($Fasm, "use32") ;wir benutzen den 32-Bit Assembler
    FasmAdd($Fasm, "mov eax,0") ;EAX=0
    FasmAdd($Fasm, "mov ecx,33") ;Schleifenzähler
    FasmAdd($Fasm, "Label1:") ;Sprungmarke
    FasmAdd($Fasm, "add eax,3") ;EAX=EAX+3
    FasmAdd($Fasm, "Loop Label1") ;ECX=ECX-1 : Springe zur Sprungmarke bis ECX=0
    FasmAdd($Fasm, "ret")
    Local $Ret = MemoryFuncCall("int", FasmGetFuncPtr($Fasm))
    _arraydisplay($ret)

    [/autoit]

    Aber der Loop kann noch mehr! Je nachdem, welches Abbruchkriterium noch gebraucht wird (bestimmt durch ZF, das Zero-Flag), kann man die Schleife schon vorher abbrechen!

    [autoit]

    FasmAdd($Fasm, "mov eax,54") ;EAX=54 ;von 54 runterzählen
    FasmAdd($Fasm, "mov ecx,33") ;Schleifenzähler
    FasmAdd($Fasm, "Label1:") ;Sprungmarke
    FasmAdd($Fasm, "sub eax,3") ;EAX=EAX-3
    FasmAdd($Fasm, "LOOPNZ Label1") ;ECX=ECX-1 : Springe zur Sprungmarke bis ECX=0 oder ZeroFlag=1
    FasmAdd($Fasm, "mov eax,ecx") ;ECX=15 d.h. die Schleife wurde 18 mal durchlaufen 18*3=54
    FasmAdd($Fasm, "ret")
    Local $Ret = MemoryFuncCall("int", FasmGetFuncPtr($Fasm))
    _arraydisplay($ret)

    [/autoit]


    Allerdings kann man das auch "zu Fuß" machen. Statt LOOP schreibt man dann

    Code
    sub ecx,1  ;ecx=ecx-1
    JNZ Label1  ;Jump if Not Zero   zum Label

    Bei dieser Gelegenheit noch eine kleine Anmerkung zu den Labels.
    Bei FASM kann man beliebig viele "anonyme" Label setzen mit @@:
    Zu diesen Labels kann man dann mit @b (backwards) zurückspringen oder mit @f (foreward) nach vorne springen

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (12. August 2010 um 04:36)

  • Super Tutorial!!!
    Trotzdem hab ich ein paar Fragen:
    Was genau ist REPNE SCASD und wann springt es wohin
    Wohin spring CMP
    Welche Größe brauche ich um einen String zurückzugeben? (mov eax,byte[string] klappt nicht...)
    Kann man mit Assembler String codieren?
    Wofür ist das Schlüsselwort "ptr", zb bei dec word ptr [esi+0e]

    Wär nett wenn du mir das erklären könntest

    EDIT:
    Gibt es in FASM soetwas:
    PROC WriteX
    ...
    ret
    ENDP WriteX

    EDIT:
    Hab ein Primzahlfinder gebaut :D

    Spoiler anzeigen
    [autoit][/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "mov eax,[esp+4]");Parameter Min.
    FasmAdd($Fasm, "cmp eax,3") ;\_
    FasmAdd($Fasm, "jl makeitthree");/ Unter 3 nicht prüfen
    FasmAdd($Fasm, "c:");von "Funktion" zurückkehren
    FasmAdd($Fasm, "push eax");Parameter min. im Stack speichern
    FasmAdd($Fasm, "xor edx,edx") ;für Division mit Modulo
    FasmAdd($Fasm, "mov ebx,2");Division durch 2
    FasmAdd($Fasm, "div ebx");dividieren
    FasmAdd($Fasm, "pop eax");eax aus dem Stack wiedererstellen (wurde bei Division verändert)
    FasmAdd($Fasm, "cmp edx,1") ;\_
    FasmAdd($Fasm, "jne setung");/ Wenn Rest<>1 dann gehe zu "Funktion" setung, man muss nur jede 2. Zahl prüfen (nur ungerade)
    FasmAdd($Fasm, "cc:");von "Funktion" zurückkehren
    FasmAdd($Fasm, "mov ebx,[esp+8]");Parameter Max.
    FasmAdd($Fasm, "l:");Hauptschleifenlabel
    FasmAdd($Fasm, "push eax");Parameter speichern
    FasmAdd($Fasm, "push ebx");---------"---------
    FasmAdd($Fasm, "mov ecx,eax");eax zurücklegen
    FasmAdd($Fasm, "dec eax");eax dekrementieren
    FasmAdd($Fasm, "lo:");Subschleifenlabel
    FasmAdd($Fasm, "mov edx,0") ;\_
    FasmAdd($Fasm, "xor edx,edx");/ Modulospeicherung vorbereiten
    FasmAdd($Fasm, "mov ebx,eax");Es soll durch eax geteilt werden, deswegen nach ebx schieben
    FasmAdd($Fasm, "mov eax,ecx");Es soll durch das zurükgelegte eax geteilt werden
    FasmAdd($Fasm, "div ebx");Division
    FasmAdd($Fasm, "cmp edx,0");Wenn Rest=0, dann keine Primzahl
    FasmAdd($Fasm, "je elo");also springe nach Fortführung der Hauptschleife
    FasmAdd($Fasm, "mov eax,ebx");eax wieder vom Anfang der Schleife wiedererstellen
    FasmAdd($Fasm, "cmp eax,2");Wenn durch 2 geteilt wurde
    FasmAdd($Fasm, "je ende");Dann springe zum Ende (weil es eine Primzahl ist,sonst wäre er zum label elo gesprungen), eax ist schon der Wert der zurückgegeben werden soll
    FasmAdd($Fasm, "dec eax");eax wiederholt dekrementieren um weiterzuprüfen
    FasmAdd($Fasm, "jmp lo");zum SChleifenanfang springen
    FasmAdd($Fasm, "elo:");label nach Subschleife
    FasmAdd($Fasm, "pop ebx");ebx von Stack wiedererstellen
    FasmAdd($Fasm, "pop eax");eax von Stack wiedererstellen
    FasmAdd($Fasm, "add eax,2");zu prüfende Zahl um 2 erhöhen (2, weil gerade Zahlen durch 2 teilbar sind)
    FasmAdd($Fasm, "cmp eax,ebx");Wenn er noch nicht beim Parameter Max. angekommen ist
    FasmAdd($Fasm, "jne l");dann wiederhole die Hauptschleife
    FasmAdd($Fasm, "jmp ende");sonst springe zum Ende
    FasmAdd($Fasm, "makeitthree:");"Funktion" Parameter Min. mindestens zu 3 machen
    FasmAdd($Fasm, "mov eax,3");in eax gespeicherter Parameter wird zu 3 gesetzt
    FasmAdd($Fasm, "jmp c");springe wieder zurück
    FasmAdd($Fasm, "setung:");"Funktion" Parameter Min. muss ungerade werden, wenn es gerade war
    FasmAdd($Fasm, "inc eax");in eax gespeicherten Parameter inkrementieren
    FasmAdd($Fasm, "jmp cc");zurückspringen
    FasmAdd($Fasm, "ende:");label ende
    FasmAdd($Fasm, "pop ebx");ebx wiedererstellen und Platz vom Stack freigeben
    FasmAdd($Fasm, "pop eax");obwohl eax schon die richtige Zahl war muss es wiedererstellt werden, weil es sonst nicht die Daten im Stack löschen wurde
    FasmAdd($Fasm, "ret 8");Ab nach draußen

    [/autoit]


    Er findet allerdings nur die erste Primzahl im Bereich von 2 Parametern (Min.,Max.).
    Ich weiß der ist sehr unübersichtlich, aber er klappt und für meine erste Assemblerfunktion finde ich es nicht schlecht (ich wette ein besserer als ich hätte das mit der Hälfte an Zeilen geschafft)
    Wens interesiert kann sich ja mal den Code angucken
    (Er berücksichtigt den 2. Parameter nur wenn er größer ist!)

    7 Mal editiert, zuletzt von TheShadowAE (22. August 2010 um 12:09)

  • Zitat

    Was genau ist REPNE SCASD und wann springt es wohin

    Das ist eine sehr mächtige Kombination zweier Befehle.
    REP (die Postfixe entsprechen denen der Sprungbefehle und beziehen sich auf die Flags) heisst Repeat also "Wiederholen". Und zwar so lange, bis ein bestimmter Zustand eines Prozessor(status-)flags erreicht ist. REP kann auf einige Befehle angewendet werden.
    SCAS vergleicht zwei Speicherstellen bestimmter Größe und setzt anhand des Ergebnisses die Statusflags.

    Ich hole etwas aus um zwei wichtige Register vorzustellen (E)DI und (E)SI. D steht für Destination (Ziel), und S für Source (Quelle)
    In 8- Bzw. 16-Bitumgebungen treten diese (Offset-) Register immer in Verbindung mit den sogenannten Segmentregistern auf, ES : DI und DS : SI. Wen es interessiert, dafür gibt es ganze Bücher^^, und ist auch für uns kein Thema.
    Nur soviel, Segmente brauchen uns nicht mehr zu kümmern, der Speicher ist linear angeordnet (intern schaufelt Windows den zwar um, aber das juckt uns nicht...). Uns interessiert nur noch die "reine" Speicherstelle.

    Also eigentlich nur noch die beiden Register ESI und EDI. Mit Quelle und Ziel kann man verschiedenste Sachen machen.
    Man kann z.B. Daten von der Quelle zum Ziel transferieren oder Quelle und Ziel vergleichen. Um jetzt längere Datensequenzen zu bearbeiten, werden die "Stringbefehle" CMPS (CoMPare String (vergleichen)) und MOVS (verschieben/kopieren) verwendet. Das Präfix bestimmt dabei die Größe B=Byte W=Word D=Doubleword
    Beispiel MOVSB kopiert ein Byte von der Adresse ESI nach der Adresse EDI. Nach dieser Operation wird (je nachdem wie das DF-Flag gesetzt ist) sowohl ESI als auch EDI incrementiert oder decrementiert. Und zwar abhängig von der Größe der transportierten Daten. Wird also per MOVS ein Byte kopiert, dann wird ESI und EDI um ein Byte (also um eine Speicherstelle) erhöht. Wird mit MOVSD ein Doubleword kopiert, erhöhen sich ESI und EDI um 4 Byte...
    Das heisst, sowohl für die Quelle als auch für das Ziel sind die Adressen für die folgende Opreation bereits geladen! Für CMPS gilt selbiges...

    SCAS vergleicht nun die Daten von EAX und Ziel, und erhöht danach automatisch das Register EDI. Bei jedem Mal, bei dem SCAS aufgerufen wird, erhöht sich also EDI. Ist jetzt der INHALT der Speicheradresse von EDI gleich EAX, dann wird u.a. das ZF (Zeroflag) gesetzt. Dieses kann nun wiederum von z.B. REP abgefragt werden.

    REPNE SCASD bedeutet also, REPeat if Not Equal StringCompare of Doubleword also ungefähr wiederhole den Stringvergleich des Doubleword an EDI so lange, wie dieses nicht gleich EAX ist. Da Not Equal eigentlich das ZeroFlag abfragt, könnte auch der Fall eintreten, dass ECX=0 ist, denn REP decrementiert ja gleichzeitig ECX! Kompliziert?^^

    Wenn nun das ZF gesetzt ist, also entweder ECX=0 oder EAX=[EDI] dann wird der nächste Befehl im Assembler ausgeführt

    Zitat

    Welche Größe brauche ich um einen String zurückzugeben? (mov eax,byte[string] klappt nicht...)

    Sobald der "String" größer als 4 Byte (=1 Dword=maximale Größe eines Registers) ist, kannst du den nicht "direkt" zurückgeben! Was du aber zurückgeben kannst, ist die Adresse zu diesem String! Da "Strings" im Sinne von Zeichenketten, also z.B. $a="Hallo, ich bin ein String!" in der Regel Nullterminiert sind, musst du einfach nur die Anfangsadresse haben und so lange Buchstaben einlesen, bis eine NULL kommt, dann ist ENDE!
    Genau aus diesem Grund Bekommt man auch nicht viel zu sehen, wenn man in AutoIt z.B. den Inhalt einer EXE-Datei in einen String liest und diese dann per MsgBox() ausgeben will. Irgendwo steht ein Nullbyte und die MsgBox-Funktion stellt nur die Zeichen bis zu diesem Nullbyte dar! Der "String" hat aber trotzdem die Länge der EXE-Datei!

    Zitat

    Kann man mit Assembler String codieren?

    Verstehe ich nicht ganz^^. Der "Assembler" bzw. die von ihm erstellten Mnemonics machen all das, was auf dem Computer abläuft. Er übersetzt die Assemblerbefehle 1:1 mit Maschinencode! Etwas anderes versteht der Prozessor nicht...
    Ein Compiler macht das etwas anders. Er "versucht" (mehr oder weniger erfolgreich), die Befehle des Programmierers so in Maschinensprache umzusetzen, daß das passiert, was der Programmierer erreichen möchte. Das ist ungleich schwieriger! Daher fabrizieren alle Compiler wesentlich mehr Maschinencode, als "eigentlich" nötig wäre.
    Die "Strings" erstellst du entweder direkt im Assembler mit z.B.
    string db 'Hallo, ich bin ein String!',0 ;die 0 ist wichtig!!^^
    oder du erstellst den String mit AutoIt und kopierst ihn mit dllstructsetdata in eine Struct. Dann kannst du den Zeiger (Pointer) auf diesen Speicherbereich mit dllstructgetptr() an den Assembler übergeben. Denn leider erlaubt AutoIt nicht, direkt die Adresse auf eine Variable zu ermitteln.

    Zitat

    Gibt es in FASM soetwas:
    PROC WriteX
    ...
    ret
    ENDP WriteX

    Ja, klar, aber nicht in dem "Embedded" Modell in der FASM.AU3. Die ist bis auf das allernötigste abgespeckt. schau mal auf der HP vom FASM nach, dort ist ein sehr schönes Dokument.

    Zitat

    Hab ein Primzahlfinder gebaut

    GEIL! :thumbup:

    Zitat

    Ich weiß der ist sehr unübersichtlich, aber er klappt und für meine erste Assemblerfunktion finde ich es nicht schlecht (ich wette ein besserer als ich hätte das mit der Hälfte an Zeilen geschafft)

    Das ist egal...Hauptsache, es funktioniert erstmal! Optimieren kann man dann immer noch!
    Aber ich würde dir raten, (ohne dass ich mich durch den Code gekämpft hätte), die Kommentare zu benutzen! Ansonsten blickst du nach 2 Wochen absolut nicht mehr durch^^
    Dabei sollte im Kommentar stehen, was du ERREICHEN WILLST!
    mov ECX,13 ;13 nach ECX
    Ist überflüssig, aber bei
    mov ECX,13 ;Zähler für die Länge des Strings für REPNZ
    versteht jeder sofort um was es geht! :thumbup:

    • Offizieller Beitrag

    Hi,
    habe ein seltsames Problem. Dein Bsp. Addition nur mit anderen (Integer)-Werten.
    Ist der erste übergebene Integer = oder ein Vielfaches von 256, wird er als 0 geführt. Ab dem Folgewert beginnt er wieder bei 1. ?(

    Spoiler anzeigen
    [autoit]

    $Fasm = FasmInit() ;FASM initialisieren
    FasmReset($Fasm) ;FASM resetten
    FasmAdd($Fasm, "use32") ;wir benutzen den 32-Bit Assembler
    FasmAdd($Fasm, "mov eax, [esp + 4]") ;erster Parameter ins EAX-Register, 4 Byte nach der Rücksprungadresse
    FasmAdd($Fasm, "mov ebx, [esp + 8]") ;zweiter Parameter ins EBX-Register
    FasmAdd($Fasm, "add eax, ebx") ;EAX = EAX + EBX
    ;ein einfaches RET reicht nun
    FasmAdd($Fasm, "ret") ;zurück zur aufrufenden Funktion
    $bytecode=FasmGetBinary($Fasm)
    ConsoleWrite($bytecode&@CRLF) ;Bytecode per Copy/Paste in das nächste Script transferieren
    MsgBox(0,"Bytecode, der vom Assembler erstellt wurde:",String(FasmGetBinary($Fasm))) ;Bytecode anzeigen
    ;die folgenden 3 Zeilen ersetzen den MemoryFuncCall()
    $tCodebuffer=dllstructcreate("byte["&stringlen($Bytecode)/2-1&"]") ;Speicher für den Bytecode reservieren
    dllstructsetdata($tCodeBuffer,1,$Bytecode) ;Bytecode in den Speicher schreiben

    [/autoit] [autoit][/autoit] [autoit]

    $Ret= DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "byte", 255, "int", 2000000, "int", 0, "int", 0);bytecode aufrufen, rückgabe in a[0], aufruf IMMER mit 4 Parametern!
    MsgBox(0,"255+2000000 - OK",$Ret[2]&" + "&$Ret[3]&" = "&$Ret[0])

    [/autoit] [autoit][/autoit] [autoit]

    $Ret= DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "byte", 256, "int", 2000000, "int", 0, "int", 0);bytecode aufrufen, rückgabe in a[0], aufruf IMMER mit 4 Parametern!
    MsgBox(0,"256+2000000 - FALSCH",$Ret[2]&" + "&$Ret[3]&" = "&$Ret[0])

    [/autoit] [autoit][/autoit] [autoit]

    $Ret= DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "byte", 512, "int", 2000000, "int", 0, "int", 0);bytecode aufrufen, rückgabe in a[0], aufruf IMMER mit 4 Parametern!
    MsgBox(0,"512+2000000 - FALSCH",$Ret[2]&" + "&$Ret[3]&" = "&$Ret[0])

    [/autoit] [autoit][/autoit] [autoit]

    FasmExit($Fasm) ;FASM aus dem Speicher entfernen

    [/autoit]

    Edit: Das kommt von Copy&Paste: Du hattest als Übergabetyp des ersten Parameters 'byte' - hatte ich nicht drauf geachtet ;)

  • Danke für die Hilfe, habe aber noch mehr Fragen/Probleme:
    Ich habe jetzt eine Funktion gebaut um Strings mit xor zu codieren/decodieren, aber leider finde ich nicht heraus wie man den Stringpointer eines mit db/dw erstellten Strings nach edi schiebt, damit es klappt:

    Spoiler anzeigen
    [autoit]

    FasmAdd($Fasm, "mov eax,[esp+4]");Stringpointer aus Parameter zu eax
    FasmAdd($Fasm, "mov esi,[eax]");str* zu str, außerdem nach esi, eax wird Rückgabe
    FasmAdd($Fasm, "mov edi,str");edi muss Pointer auf einen String sein <-- Fehler
    ;
    FasmAdd($Fasm, "schleife:");Label für Schleife
    FasmAdd($Fasm, "cmp word[esi],0");Wenn Stringende
    FasmAdd($Fasm, "je ende");dann beende
    FasmAdd($Fasm, "mov ax,word[esi]");sonst speichere das erste word in ax(eax=32 bit,ax=16bit)
    FasmAdd($Fasm, "xor ax,25");verschlüssele es
    FasmAdd($Fasm, "mov word[esi],ax");und schiebe es wieder zurück
    FasmAdd($Fasm, "movsw");dann schiebe ein word in den Zielstring
    FasmAdd($Fasm, "jmp schleife");und wiederhole die Schleife
    ;
    FasmAdd($Fasm, "ende:");Label für Schleifen-/Funktions-Ende
    FasmAdd($Fasm, "movsw");die 0 muss noch hinter den String
    FasmAdd($Fasm, "mov eax,edi");String aus edi, nach eax, damit der (de)codierte String zurückgegeben wird
    FasmAdd($Fasm, "ret 4");Funktionsende
    FasmAdd($Fasm, "str dw 0");leerer String für neuen String

    [/autoit]
    Spoiler anzeigen
    [autoit]

    FasmAdd($Fasm, "mov eax,[esp+4]");Stringpointer aus Parameter zu eax
    FasmAdd($Fasm, "mov esi,[eax]");str* zu str, außerdem nach esi, eax wird Rückgabe
    FasmAdd($Fasm, "mov edi,str");edi muss Pointer auf einen String sein <-- Fehler
    ;
    FasmAdd($Fasm, "schleife:");Label für Schleife
    FasmAdd($Fasm, "cmp byte[esi],0");Wenn Stringende
    FasmAdd($Fasm, "je ende");dann beende
    FasmAdd($Fasm, "mov al,byte[esi]");sonst speichere das erste word in ax(eax=32 bit,ax=16bit)
    FasmAdd($Fasm, "xor al,25");verschlüssele es
    FasmAdd($Fasm, "mov byte[esi],al");und schiebe es wieder zurück
    FasmAdd($Fasm, "movsb");dann schiebe ein word in den Zielstring
    FasmAdd($Fasm, "jmp schleife");und wiederhole die Schleife
    ;
    FasmAdd($Fasm, "ende:");Label für Schleifen-/Funktions-Ende
    FasmAdd($Fasm, "movsb");die 0 muss noch hinter den String
    FasmAdd($Fasm, "mov eax,edi");String aus edi, nach eax, damit der (de)codierte String zurückgegeben wird
    FasmAdd($Fasm, "ret 4");Funktionsende
    FasmAdd($Fasm, "str db 0");leerer String für neuen String

    [/autoit]

    PS:
    Hab jetzt mein "Beispiel" kommentiert

    5 Mal editiert, zuletzt von TheShadowAE (22. August 2010 um 13:29)

  • @ Bugfix, das hat sich ja erledigt^^

    TheShadowAE

    Spoiler anzeigen
    [autoit]

    $string="Hallo Test!"

    [/autoit] [autoit][/autoit] [autoit]

    Dim $Fasm = FasmInit()
    FasmReset($Fasm)
    FasmAdd($Fasm, "use32")
    FasmAdd($Fasm, "org " & FasmGetBasePtr($Fasm))
    FasmAdd($Fasm, "mov eax,[esp+4]");Stringpointer aus Parameter zu eax
    FasmAdd($Fasm, "mov esi,[eax]");str* zu str, außerdem nach esi, eax wird Rückgabe
    FasmAdd($Fasm, "mov edi,puffer");edi muss Pointer auf einen String sein <-- Fehler
    ;
    FasmAdd($Fasm, "schleife:");Label für Schleife
    FasmAdd($Fasm, "cmp word[esi],0");Wenn Stringende
    ;~ FasmAdd($Fasm, "mov eax,dword[esi]")
    ;~ FasmAdd($Fasm, "ret 4");Funktionsende
    FasmAdd($Fasm, "je ende");dann beende
    FasmAdd($Fasm, "mov ax,word[esi]");sonst speichere das erste word in ax(eax=32 bit,ax=16bit)
    FasmAdd($Fasm, "xor ax,25");verschlüssele es
    FasmAdd($Fasm, "mov word[esi],ax");und schiebe es wieder zurück
    FasmAdd($Fasm, "movsw");dann schiebe ein word in den Zielstring
    FasmAdd($Fasm, "jmp schleife");und wiederhole die Schleife
    ;
    FasmAdd($Fasm, "ende:");Label für Schleifen-/Funktions-Ende
    FasmAdd($Fasm, "movsw");die 0 muss noch hinter den String
    FasmAdd($Fasm, "mov eax,puffer");String aus edi, nach eax, damit der (de)codierte String zurückgegeben wird
    FasmAdd($Fasm, "ret 4");Funktionsende
    FasmAdd($Fasm, "puffer dw 1 dup(100)");hundert "words" reservieren für zielstring

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $Ret = MemoryFuncCall("wstr", FasmGetFuncPtr($Fasm), "wstr*", $string)
    msgbox(0,"kodieren XOR "&$string,$ret[0])
    ;_arraydisplay($ret)

    [/autoit] [autoit][/autoit] [autoit]

    $string=$ret[0] ;kodierter string
    $Ret = MemoryFuncCall("wstr", FasmGetFuncPtr($Fasm), "wstr*", $string)
    msgbox(0,"DEkodieren XOR "&$string,$ret[0])
    exit

    [/autoit]

    Mal abgesehen davon, daß du nur die falsche Adresse zurückgegebeb hattest (EDI zeigt ja nach der Schreiberei der Daten HINTER den String und nicht an den Anfang!) funktioniert das einwandfrei.
    Du brauchst den "pufferl" aber nicht unbedingt, du überschreibst schreibst ja den "Eingangsstring" direkt.
    Um übrigens "sauschnell" Strings bzw Speicher zu XORen, gibt es den SSE-Befehl XORPS oder PXOR, damit XORed man 128 Bit auf einen Streich. Aber SSE bzw MMX wollte ich später ins TUT integrieren^^

  • Um übrigens "sauschnell" Strings bzw Speicher zu XORen, gibt es den SSE-Befehl XORPS oder PXOR, damit XORed man 128 Bit auf einen Streich. Aber SSE bzw MMX wollte ich später ins TUT integrieren^^

    Und was ist wenn man einen Uhralten CPU hat der noch kein SSE oder MMX unterstützt ? Schmiert die ganze Kiste ab oder gibts nur nen Error.


    //Edit: Hab mich mal schlau gemacht. SSE und MMX ist schon ewig standart. Müsste also jeder der mindestens Win 95 nutzt im CPU haben.

    //Edit2: Haben AMD Prozessoren den gleichen Befehlssatz?

  • Hm also habe ich nur den Fehler gemacht es puffer zu nennen und mov eax,edi zu mov eax,puffer zu machen?
    Was ist das denn für ein komischer Fehler

    EDIT:
    Aha die Bytevariante kann nur str und ist äquivalent mit wordvariante mit wstr, wordvariante mit str funktioniert auch, aber es kommt etwas anderes als bei der bytevariante mit str, die bytevariante mit wstr klappt nicht
    Somit hätten wir dann also eine Unicode/Asciicode verschlüsselungsfunktion gemacht

    2 Mal editiert, zuletzt von TheShadowAE (22. August 2010 um 14:02)

  • Zitat

    Und was ist wenn man einen Uhralten CPU hat der noch kein SSE oder MMX unterstützt ? Schmiert die ganze Kiste ab oder gibts nur nen Error.

    Da wird natürlich vorher abgefragt (per Assembler), ob die CPU SSE/SSE2/3/4 und/oder MMX überhaupt unterstützt. Sind nur einige Byte...

    Zitat

    //Edit2: Haben AMD Prozessoren den gleichen Befehlssatz?

    yepp, AMD hat übrigens wunderschöne Manuals...besonders die zur Optimierung sollten zu den Standardwerken für C bzw C++ - Programmierer gehören!
    Bsp: SSE
    Aber auch an den Seiten von Agner Fog (lesenswerte Manuals) wird man über kurz oder lang als Assemblerprogrammierer nicht vorbeikommen...

  • Zitat

    Hm also habe ich nur den Fehler gemacht es puffer zu nennen und mov eax,edi zu mov eax,puffer zu machen?
    Was ist das denn für ein komischer Fehler

    str ist reserviert, da Assemblerbefehl^^
    Und wenn dein Zeiger EAX (EDI) auf das Ende des Strings zeigt, dann kann auch nur ab dort eingelesen werden.

    [autoit]

    FasmAdd($Fasm, "ende:");Label für Schleifen-/Funktions-Ende
    FasmAdd($Fasm, "movsw");die 0 muss noch hinter den String
    FasmAdd($Fasm, "lea eax,[edi-22]"); EAX= EDI-22 also wieder an den anfang des strings, wenn du nun die stringlänge zwischenspeicherst, kannst du auch [edi-ebx] machen!
    FasmAdd($Fasm, "ret 4");Funktionsende
    FasmAdd($Fasm, "puffer dw 1 dup(100)");hundert "words" reservieren für zielstring

    [/autoit]

    LEA wollte ich im nächsten TUT-Teil abhandeln, ein sehr mächtiger Befehl, der einen Shift, zwei Additionen und einen Move in einem Befehl unterbekommt!

  • Achsooo, danke, meine neue Version klappt jetzt so also:

    Spoiler anzeigen
    [autoit]

    FasmAdd($Fasm, "mov eax,[esp+4]");Stringpointer aus Parameter zu eax
    FasmAdd($Fasm, "mov eax,[esp+4]");Stringpointer aus Parameter zu eax
    FasmAdd($Fasm, "mov esi,[eax]");str* zu str, außerdem nach esi, eax wird Rückgabe
    FasmAdd($Fasm, "mov edi,nstr");edi muss Pointer auf einen String sein <-- Fehler
    FasmAdd($Fasm, "schleife:");Label für Schleife
    FasmAdd($Fasm, "cmp word[esi],0");Wenn Stringende
    FasmAdd($Fasm, "je ende");dann beende
    FasmAdd($Fasm, "mov ax,word[esi]");sonst speichere das erste word in ax(eax=32 bit,ax=16bit)
    FasmAdd($Fasm, "xor ax,[esp+8]");verschlüssele es
    FasmAdd($Fasm, "mov word[esi],ax");und schiebe es wieder zurück
    FasmAdd($Fasm, "movsw");dann schiebe ein word in den Zielstring
    FasmAdd($Fasm, "jmp schleife");und wiederhole die Schleife
    FasmAdd($Fasm, "ende:");Label für Schleifen-/Funktions-Ende
    FasmAdd($Fasm, "movsw");die 0 muss noch hinter den String
    FasmAdd($Fasm, "mov eax,nstr");String aus edi, nach eax, damit der (de)codierte String zurückgegeben wird
    FasmAdd($Fasm, "ret 8");Funktionsende
    FasmAdd($Fasm, "nstr dw 0");leerer String für neuen String

    [/autoit]

    Und wer sich wundert warum es bei mir vermeindlich ohne org geht (ich benutze org) der guckt sich mein ganzen Code an:

    Spoiler anzeigen
    [autoit]


    #include "FASM.au3"
    #include <Array.au3>
    Opt("MustDeclareVars", 1)

    [/autoit] [autoit][/autoit] [autoit]

    ; Initial a fasm object
    Global $Fasm = FasmInit()

    [/autoit] [autoit][/autoit] [autoit]

    ;##########################
    F3()
    ;##########################
    ;FasmCompile($Fasm)

    [/autoit] [autoit][/autoit] [autoit]

    ; Release the asm object
    FasmExit($Fasm)
    Exit

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func F3()
    _new()
    FasmAdd($Fasm, "mov eax,[esp+4]");Stringpointer aus Parameter zu eax
    FasmAdd($Fasm, "mov esi,[eax]");str* zu str, außerdem nach esi, eax wird Rückgabe
    FasmAdd($Fasm, "mov edi,nstr");edi muss Pointer auf einen String sein <-- Fehler
    FasmAdd($Fasm, "schleife:");Label für Schleife
    FasmAdd($Fasm, "cmp word[esi],0");Wenn Stringende
    FasmAdd($Fasm, "je ende");dann beende
    FasmAdd($Fasm, "mov ax,word[esi]");sonst speichere das erste word in ax(eax=32 bit,ax=16bit)
    FasmAdd($Fasm, "xor ax,[esp+8]");verschlüssele es
    FasmAdd($Fasm, "mov word[esi],ax");und schiebe es wieder zurück
    FasmAdd($Fasm, "movsw");dann schiebe ein word in den Zielstring
    FasmAdd($Fasm, "jmp schleife");und wiederhole die Schleife
    FasmAdd($Fasm, "ende:");Label für Schleifen-/Funktions-Ende
    FasmAdd($Fasm, "movsw");die 0 muss noch hinter den String
    FasmAdd($Fasm, "mov eax,nstr");String aus edi, nach eax, damit der (de)codierte String zurückgegeben wird
    FasmAdd($Fasm, "ret 8");Funktionsende
    FasmAdd($Fasm, "nstr dw 0");leerer String für neuen String
    ;
    FasmCompile($Fasm)
    If @Error Then
    Local $Error = FasmGetLastError()
    ConsoleWrite("Error Code: " & $Error[$FASMERRINDEX_CODE] & @CRLF)
    ConsoleWrite("Error Message: " & $Error[$FASMERRINDEX_MESSAGE] & @CRLF)
    ConsoleWrite("Error LineNumber: " & $Error[$FASMERRINDEX_LINENUMBER] & @CRLF)
    ConsoleWrite("Error Line: " & $Error[$FASMERRINDEX_LINE] & @CRLF)
    Else
    ConsoleWrite(String(FasmGetBinary($Fasm)) & @CRLF)
    EndIf
    Local $timer=TimerInit()
    Local $ret = MemoryFuncCall("str", FasmGetFuncPtr($Fasm), "str*", "Hallo", "int", 25)
    Local $diff=TimerDiff($timer)
    MsgBox(0,$diff,$ret[0])
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func F2()
    _new()
    FasmAdd($Fasm, "mov eax,[esp+4]");Parameter Min.
    FasmAdd($Fasm, "cmp eax,3") ;\_
    FasmAdd($Fasm, "jl makeitthree");/ Unter 3 nicht prüfen
    FasmAdd($Fasm, "c:");von "Funktion" zurückkehren
    FasmAdd($Fasm, "push eax");Parameter min. im Stack speichern
    FasmAdd($Fasm, "xor edx,edx") ;für Division mit Modulo
    FasmAdd($Fasm, "mov ebx,2");Division durch 2
    FasmAdd($Fasm, "div ebx");dividieren
    FasmAdd($Fasm, "pop eax");eax aus dem Stack wiedererstellen (wurde bei Division verändert)
    FasmAdd($Fasm, "cmp edx,1") ;\_
    FasmAdd($Fasm, "jne setung");/ Wenn Rest<>1 dann gehe zu "Funktion" setung, man muss nur jede 2. Zahl prüfen (nur ungerade)
    FasmAdd($Fasm, "cc:");von "Funktion" zurückkehren
    FasmAdd($Fasm, "mov ebx,[esp+8]");Parameter Max.
    FasmAdd($Fasm, "l:");Hauptschleifenlabel
    FasmAdd($Fasm, "push eax");Parameter speichern
    FasmAdd($Fasm, "push ebx");---------"---------
    FasmAdd($Fasm, "mov ecx,eax");eax zurücklegen
    FasmAdd($Fasm, "dec eax");eax dekrementieren
    FasmAdd($Fasm, "lo:");Subschleifenlabel
    FasmAdd($Fasm, "mov edx,0") ;\_
    FasmAdd($Fasm, "xor edx,edx");/ Modulospeicherung vorbereiten
    FasmAdd($Fasm, "mov ebx,eax");Es soll durch eax geteilt werden, deswegen nach ebx schieben
    FasmAdd($Fasm, "mov eax,ecx");Es soll durch das zurükgelegte eax geteilt werden
    FasmAdd($Fasm, "div ebx");Division
    FasmAdd($Fasm, "cmp edx,0");Wenn Rest=0, dann keine Primzahl
    FasmAdd($Fasm, "je elo");also springe nach Fortführung der Hauptschleife
    FasmAdd($Fasm, "mov eax,ebx");eax wieder vom Anfang der Schleife wiedererstellen
    FasmAdd($Fasm, "cmp eax,2");Wenn durch 2 geteilt wurde
    FasmAdd($Fasm, "je ende");Dann springe zum Ende (weil es eine Primzahl ist,sonst wäre er zum label elo gesprungen), eax ist schon der Wert der zurückgegeben werden soll
    FasmAdd($Fasm, "dec eax");eax wiederholt dekrementieren um weiterzuprüfen
    FasmAdd($Fasm, "jmp lo");zum SChleifenanfang springen
    FasmAdd($Fasm, "elo:");label nach Subschleife
    FasmAdd($Fasm, "pop ebx");ebx von Stack wiedererstellen
    FasmAdd($Fasm, "pop eax");eax von Stack wiedererstellen
    FasmAdd($Fasm, "add eax,2");zu prüfende Zahl um 2 erhöhen (2, weil gerade Zahlen durch 2 teilbar sind)
    FasmAdd($Fasm, "cmp eax,ebx");Wenn er noch nicht beim Parameter Max. angekommen ist
    FasmAdd($Fasm, "jne l");dann wiederhole die Hauptschleife
    FasmAdd($Fasm, "jmp ende");sonst springe zum Ende
    FasmAdd($Fasm, "makeitthree:");"Funktion" Parameter Min. mindestens zu 3 machen
    FasmAdd($Fasm, "mov eax,3");in eax gespeicherter Parameter wird zu 3 gesetzt
    FasmAdd($Fasm, "jmp c");springe wieder zurück
    FasmAdd($Fasm, "setung:");"Funktion" Parameter Min. muss ungerade werden, wenn es gerade war
    FasmAdd($Fasm, "inc eax");in eax gespeicherten Parameter inkrementieren
    FasmAdd($Fasm, "jmp cc");zurückspringen
    FasmAdd($Fasm, "ende:");label ende
    FasmAdd($Fasm, "pop ebx");ebx wiedererstellen und Platz vom Stack freigeben
    FasmAdd($Fasm, "pop eax");obwohl eax schon die richtige Zahl war muss es wiedererstellt werden, weil es sonst nicht die Daten im Stack löschen wurde
    FasmAdd($Fasm, "ret 8");Ab nach draußen
    ;
    FasmCompile($Fasm)
    If @Error Then
    Local $Error = FasmGetLastError()
    ConsoleWrite("Error Code: " & $Error[$FASMERRINDEX_CODE] & @CRLF)
    ConsoleWrite("Error Message: " & $Error[$FASMERRINDEX_MESSAGE] & @CRLF)
    ConsoleWrite("Error LineNumber: " & $Error[$FASMERRINDEX_LINENUMBER] & @CRLF)
    ConsoleWrite("Error Line: " & $Error[$FASMERRINDEX_LINE] & @CRLF)
    Else
    ConsoleWrite(String(FasmGetBinary($Fasm)) & @CRLF)
    EndIf
    Local $timer=TimerInit()
    Local $ret = MemoryFuncCall("int", FasmGetFuncPtr($Fasm), "int", 1000, "int", 0)
    Local $diff=TimerDiff($timer)
    MsgBox(0,$diff,$ret[0])
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func F1()
    _new()
    FasmAdd($Fasm, "mov eax, [esp + 4]")
    FasmAdd($Fasm, "mov ebx, [esp + 8]")
    FasmAdd($Fasm, "add eax, ebx")
    FasmAdd($Fasm, "ret 8")
    ConsoleWrite(String(FasmGetBinary($Fasm))&@CRLF)
    Local $Ret = MemoryFuncCall("int", FasmGetFuncPtr($Fasm), "int", 1, "int", 2)
    MsgBox(0,"",$Ret[1]&"+"&$Ret[2]&"="&$Ret[0])
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _new()
    FasmReset($Fasm)
    FasmAdd($Fasm, "use32")
    FasmAdd($Fasm, "org "&FasmGetBasePtr($Fasm))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _ByteCodeCall($txt)
    Local $tCodebuffer=dllstructcreate("byte["&stringlen($txt)/2-1&"]")
    dllstructsetdata($tCodeBuffer,1,$txt)
    Return DllCall("user32.dll", "", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "int", 0, "int", 0, "int", 0, "int", 0)
    EndFunc

    [/autoit]
  • Sehr schön, ggf sollten wir eine "Funktionssammlung" für schnelle Funktionen (mit Assemblerunterstützung) eröffnen.
    Da ist ja schon einiges auch im "blauen" Forum zusammengekommen, Verschlüsselungen vor allem.

    @Shadow, sehr nice kommentiert, das liest sich "wie ein Buch!". :thumbup:

  • Andy: Danke. Ich werde erstmal weiter mit COM Anwendungen machen. Is ja eigentlich auch egal was das ganze für ne Endung hat.

    Sry 4 OT aber ich habe mal einen kleinen For Schleifen Test machen wie schnell Assembler ist.

    Führt mal den Code aus und schaut in die Console bei SciTe

    [autoit]

    #include "FASM.au3"
    #include <Array.au3>

    [/autoit][autoit][/autoit][autoit]

    Dim $Fasm = FasmInit()

    [/autoit][autoit][/autoit][autoit]

    FasmReset($Fasm)
    FasmAdd($Fasm, "use32")
    FasmAdd($Fasm, "org " & FasmGetBasePtr($Fasm)) ;Dem Assembler die zzt aktuellen Segmentregister bzw Offsets mitteilen
    FasmAdd($Fasm, "mov eax,0")
    FasmAdd($Fasm, "for:")
    FasmAdd($Fasm, "add eax,1")

    [/autoit][autoit][/autoit][autoit]

    FasmAdd($Fasm, "CMP eax,1000000")
    FasmAdd($Fasm, "JNE for")

    [/autoit][autoit][/autoit][autoit]

    FasmAdd($Fasm, "CMP eax,1000000")
    FasmAdd($Fasm, "JE ende")

    [/autoit][autoit][/autoit][autoit]

    FasmAdd($Fasm, "ende:")
    FasmAdd($Fasm, "ret")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    ;~ ConsoleWrite(String(FasmGetBinary($Fasm)) & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    $hTimer = TimerInit()
    $a = MemoryFuncCall("int", FasmGetFuncPtr($Fasm))
    ConsoleWrite("ASM:" & TimerDiff($hTimer) & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    $hTimer = TimerInit()
    For $x = 1 To 1000000
    Next
    ConsoleWrite("For:" & TimerDiff($hTimer) & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    ;~ _ArrayDisplay($a)
    FasmExit($Fasm)

    [/autoit]
  • ja, indem du entweder (in AutoIt) eine Struct anlegst und dort die Elemente per Index aufrufst (wie bei AutoIt) oder dein Array als

    Code
    Array dd 1 dup(100)   ;erstellt ein  "Array" von 100 dwords
    Zitat

    ; angenommen, der inhalt von array[5] soll abgefragt werden
    ;mov eax,[basepointer_array + indexregister *4] ;4 byte pro wort
    mov ebx,5 ;index
    mov eax,[array+ebx*4] ;inhalt von array[5]

  • Dann mach ich doch auch direkt einmal vom Thread Gebrauch:
    Ich hab versucht ein Bild aus Zufallsfarben zu erstellen, leider bleibt das Bild leer (oder es wird nicht angezeigt)
    Kann es sein dass GDI+ nicht mit Bmp32 abkommt oder hab ich ein Fehler im Code? (z.B. beim Zufall)

    Mein Code:

    Funktion F5
    [autoit]

    #include "FASM.au3"
    #include <Array.au3>
    #include <Winapi.au3>
    #include <GDIConstants.au3>
    #include <GDIPlus.au3>
    Opt("MustDeclareVars", 1)

    [/autoit] [autoit][/autoit] [autoit]

    ; Initial a fasm object
    Global $Fasm = FasmInit()

    [/autoit] [autoit][/autoit] [autoit]

    ;##########################
    F5()
    ;##########################
    ;FasmCompile($Fasm)

    [/autoit] [autoit][/autoit] [autoit]

    ; Release the asm object
    FasmExit($Fasm)
    Exit

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func F5() ;Zufallsbild
    _new()
    ;
    FasmAdd($Fasm, "mov eax,[esp+4]");Width in eax
    FasmAdd($Fasm, "mov [w],eax");Width in w speichern
    FasmAdd($Fasm, "mov eax,[esp+8]");Height in eax
    FasmAdd($Fasm, "mov [h],eax");Height in h speichern
    FasmAdd($Fasm, "mov edi,[esp+12]");Pointer für Bitmapdaten and Destination schreiben

    [/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "push edi");etwas in stack schreiben für die Zufallsfunktion

    [/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "mov ecx,[w]"); ecx als Zähler für For-Schleife (x) For ecx=w to 0 step -1
    FasmAdd($Fasm, "for_x:");Label für Schleife
    FasmAdd($Fasm, "mov edx,[h]"); edx als Zähler für For-Schleife (y) For edx=h to 0 step -1
    FasmAdd($Fasm, "for_y:");Label für Schleife
    FasmAdd($Fasm, "jmp zufall");Zufallsfunktion aufrufen
    FasmAdd($Fasm, "back:");Label zum zurückspringen
    FasmAdd($Fasm, "stosd");in eax gespeicherte Farbe (durch Zufallsfunktion dareingeschrieben) nach edi (Bitmap) schreiben
    FasmAdd($Fasm, "dec edx");Schleifenzähler -1
    FasmAdd($Fasm, "jnz for_y");Solange Schleifenzähler nicht 0 wiederhole Schleife
    FasmAdd($Fasm, "dec ecx");Schleifenzähler -1
    FasmAdd($Fasm, "jnz for_x");Solange Schleifenzähler nicht 0 wiederhole Schleife

    [/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "jmp ende");Nach den Schleifen an das Ende springen

    [/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "zufall:");Zufallfunktionslabel
    FasmAdd($Fasm, "pop eax");altes Ergebnis in eax schreiben
    FasmAdd($Fasm, "sub eax,1");minus 1 rechnen
    FasmAdd($Fasm, "imul eax,7141");mal 7141 rechnen
    FasmAdd($Fasm, "add eax,54773");plus 54773 rechnen
    FasmAdd($Fasm, "push eax");und neues ergebnis im Stack speichern
    FasmAdd($Fasm, "jmp back");zurückspringen

    [/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "ende:");Label für Ende
    FasmAdd($Fasm, "pop eax");Stack freigeben
    FasmAdd($Fasm, "ret 12");Ende

    [/autoit] [autoit][/autoit] [autoit]

    FasmAdd($Fasm, "w dd 0");Widthvariable reservieren
    FasmAdd($Fasm, "h dd 0");Heightvariable reservieren
    ;
    FasmCompile($Fasm)
    If @Error Then
    Local $Error = FasmGetLastError()
    ConsoleWrite("Error Code: " & $Error[$FASMERRINDEX_CODE] & @CRLF)
    ConsoleWrite("Error Message: " & $Error[$FASMERRINDEX_MESSAGE] & @CRLF)
    ConsoleWrite("Error LineNumber: " & $Error[$FASMERRINDEX_LINENUMBER] & @CRLF)
    ConsoleWrite("Error Line: " & $Error[$FASMERRINDEX_LINE] & @CRLF)
    Else
    ConsoleWrite(String(FasmGetBinary($Fasm)) & @CRLF)
    EndIf
    Local $w=100,$h=100,$bmp,$hbmp,$dc
    $dc=_CreateNewBmp32($w,$h,$bmp,$hbmp)
    Local $timer=TimerInit()
    Local $ret = MemoryFuncCall("int", FasmGetFuncPtr($Fasm), "int", $w, "int", $h, "ptr", $bmp)
    Local $diff=TimerDiff($timer)
    MsgBox(0,"",$diff)
    _ImageShow($hbmp)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _ImageShow($img,$titel="",$x=-1,$y=-1)
    If $img=0 Then Return -1
    Local $wx,$wy
    If $x=-1 or $x>@DesktopWidth-50 Then
    $x=_GDIPlus_ImageGetWidth($img)
    if $x>@DesktopWidth-50 Then $x=@DesktopWidth-50
    EndIf
    If $y=-1 or $y>@DesktopWidth-50 Then
    $y=_GDIPlus_ImageGetHeight($img)
    if $y>@DesktopWidth-50 Then $y=@DesktopWidth-50
    EndIf
    $wx=$x
    $wy=$y
    Local $gui=GUICreate($titel,$x,$y,Default,Default,BitOR(0x00C00000,0x00080000)) ;bitor($WS_CAPTION,$WS_SYSMENU)
    GUISetState(@SW_SHOW,$gui)
    Local $gra=_GDIPlus_GraphicsCreateFromHWND($gui)
    Local $buffer=_GDIPlus_BitmapCreateFromGraphics($wx,$wy,$gra)
    Local $backgra=_GDIPlus_ImageGetGraphicsContext($buffer)
    _GDIPlus_GraphicsSetSmoothingMode($backgra,2)
    _GDIPlus_GraphicsClear($backgra)
    _GDIPlus_GraphicsDrawImageRect($backgra,$img,0,0,$wx,$wy)
    While GUIGetMsg()<>-3 ;$GUI_EVENT_CLOSE
    _WinAPI_RedrawWindow($gui, "", "", 1280) ;$RDW_UPDATENOW + $RDW_FRAME
    _GDIPlus_GraphicsDrawImageRect($gra,$buffer,0,0,$wx,$wy)
    Sleep(10)
    WEnd
    _GDIPlus_GraphicsDispose($backgra)
    _GDIPlus_BitmapDispose($buffer)
    _GDIPlus_GraphicsDispose($gra)
    GUIDelete($gui)
    Return 1
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _CreateNewBmp32($iwidth, $iheight, ByRef $ptr, ByRef $hbmp) ;erstellt leere 32-bit-Bitmap; Rückgabe DC und ptr und handle auf die Bitmapdaten
    ;by Andy
    Local $hcdc = _WinAPI_CreateCompatibleDC(0) ;Desktop-Kompatiblen DeviceContext erstellen lassen
    Local $tBMI = DllStructCreate($tagBITMAPINFO) ;Struktur der Bitmapinfo erstellen und Daten eintragen
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4);Structgröße abzüglich der Daten für die Palette
    DllStructSetData($tBMI, "Width", $iwidth)
    DllStructSetData($tBMI, "Height", -$iheight) ;minus =standard = bottomup
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", 32) ;32 Bit = 4 Bytes => AABBGGRR
    Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    $hbmp = $adib[0] ;hbitmap handle auf die Bitmap, auch per GDI+ zu verwenden
    $ptr = $adib[4] ;pointer auf den Anfang der Bitmapdaten, vom Assembler verwendet
    ;_arraydisplay($adib)
    _WinAPI_SelectObject($hcdc, $hbmp) ;objekt hbitmap in DC
    Return $hcdc ;DC der Bitmap zurückgeben
    EndFunc ;==>_CreateNewBmp32

    [/autoit]
  • Hi, habs gerade gemerkt, der Handle hbmp der _CreateNewBitmap32() ist offensichtlich nicht zu benutzen, ich weiss, dass ich die Funktion ziemlich gekürzt hatte, scheinbar war einiges, was ich rausgeschmissen hatte, doch nicht so überflüssig^^
    Bis auf weiters kann man mit GDI+-DRAW-Befehlen so auf die mit _CreateNewBitmap32() erzeugten Bitmaps zugreifen:

    [autoit]

    local $hbmp_buffer,$ptr_buffer
    $hdc_buffer=_CreateNewBmp32($w, $h,$ptr_buffer, $hbmp_buffer)
    $hGraphic_w = _GDIPlus_GraphicsCreateFromHDC($hdc_buffer)
    _GDIPlus_GraphicsDrawline($hGraphic_w, 10, 10,400,200,$hpen)

    [/autoit]
  • Ah Danke Andy. Aber wenn ich folgenden Code ausführe schmiert mir die ganze sache ab. Sollte eigentlich 2 returnen

    [autoit]

    #include "FASM.au3"
    #include <Array.au3>
    $Fasm = FasmInit()
    FasmReset($Fasm)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    fa("mov ebx,1")
    fa("mov [array+ebx*4],2")

    [/autoit][autoit][/autoit][autoit]

    fa("mov eax,[array+ebx*4]")

    [/autoit][autoit][/autoit][autoit]

    fa("ret")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    fa("array dd 1 dup(3)")

    [/autoit][autoit][/autoit][autoit]

    ConsoleWrite(String(FasmGetBinary($Fasm)) & @CRLF)
    $a = MemoryFuncCall("int", FasmGetFuncPtr($Fasm))
    _ArrayDisplay($a)

    [/autoit][autoit][/autoit][autoit]

    Func fa($str) ; Nur für die bequemlichkeit ^^
    FasmAdd($Fasm, $str)
    EndFunc ;==>fa

    [/autoit][autoit][/autoit][autoit]

    FasmExit($Fasm)

    [/autoit]

    //Edit: Ich habe folgenden Code: Warum wird nicht 2 mal ausgegeben ?