Einzelnen Beitrag anzeigen

Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Inline ASM für Win32 - Einsteiger Crashkurs

  Alt 5. Feb 2007, 13:45
Schönes Tut
(Ich bin nur zufällig durch deine Signatur hierher gekommen. Manchmal ist man aber auch neugierig...)

Was einen Anfänger verwirren könnte ist folgende Zeile:
Delphi-Quellcode:
function ShowText : PChar;
asm
  JMP @start
  @test: DB 'Hallo Du!', 0
  @start: LEA EAX, @test
  RET
end;
Du sprichst davon, dass hinter dem Label test eine Variable steht. Das könnte für Frustration sorgen, da die Speicherseiten in die der Code am Anfang geladen werden, "nur" mit 'Execute and Read' ausgestattet sind. Demnach kann man da nicht speichern und demnach ist es keine Variable sondern eine Konstante. Stört in deiner Funktion ja auch nicht weiter, denn du greifst ja nicht schreibend auf diese Speicherplätze zu.
Aber der eine oder andere könnte ja auf die Idee kommen, auf diese Art lokale Variablen anzulegen. Und das klappt nicht (==>Frustration).


Also müsste man (insofern du überhaupt willst) etwas über lokale Variablen erzählen (EBP+Stack)


Oder, man holt ganz weit aus (da ich im Erklären/Tut schreiben nicht so gut bin, nehme ich lieber gleich Code):
Delphi-Quellcode:
var MBI: TMemoryBasicInformation;
    tmp:integer;
    memory:pointer;
begin
  memory:=@Showtext;
  VirtualQuery(memory, MBI, SizeOf(MBI));
  Virtualprotect(memory,mbi.RegionSize,page_execute_readWRITE,@tmp);
...und verändert einfach die Zugriffsrechte auf die Speicherseiten.
Jetzt könnte man mit "mov byte ptr [eax],64" aus Dem "H" von Hallo ein "A" machen.


Oder man legt die Funktion in einen neu alloziierten Speicherbereich und tobt sich da aus (inkl. selbst modifiziertem code)

Delphi-Quellcode:
program Pasm;

{$APPTYPE CONSOLE}

uses windows;


//Die Assembler-Routine mit einer statischen/lokalen Variable hinter @1
//Hier wird der Parameter c entsprechend mit add (oder sub) zur statischen Variable @1 gerechnet und zurückgegeben
function testasm(c:integer):integer;
asm
     jmp @2 //Variable überspringen

 @1: dd 10 //unsere 32bit-Variable (static)

 @2: call @3 //Addresse von @1 in edx speichern
 @3: pop edx
     sub edx,9

     add eax,[edx] //@1 zu c addieren

     //Speichern des Ergebnisses in @1
     mov [edx],eax //normalerweise: EAccessViolation;
                    //aber wir dürfen ja in unserem eigenen Speicherbereich (siehe VirtualAlloc)schreiben
     
     {Hier wäre eigentlich soweit Schluss, aber man kann ja auch noch etwas rumspielen ;-)
      und mal einen Befehl verändern}

     // verändern von "add eax,[edx]" zu "sub eax,[edx]"
     // =>verändern von $0302 zu $2B02
     //und natürlich auch wieder zurück
     add edx,13 //Addresse auf den add-Befehl errechnen
     cmp byte ptr [edx],$03 //gucken, was drinn ist
     je @4
     mov byte ptr [edx],$03 //und ändern
     ret
 @4: mov byte ptr [edx],$2b //oder eben wieder zurückändern
end;

//wird als Referenz benötigt um "size" zu bestimmen
procedure dispatch;
asm
  nop
end;

var memory:pointer;
    size:cardinal;
    result:integer;
    i:integer;
begin

  //function testasm in eine neue Speicherseite kopieren -->memory
  size:=cardinal(@dispatch)-cardinal(@testasm); //Größe der Funktion testasm ermitteln
  memory:=Virtualalloc(nil,size,MEM_COMMIT,PAGE_EXECUTE_READWRITE); //Ich will auf meinem neuen Speicherbereich (memory)
                                                                    //ausführen,lesen und schreiben
  movememory(memory,@testasm,size); //copy

  //kleine Test-Schleife
  for i:=1 to 10 do begin
    asm
      mov eax,i
      call memory
      mov result,eax
    end;
    writeln(result);
  end;

  //folgende Zeile würde hier so nicht funktionieren
  //writeln(testasm(2));

  virtualfree(memory,size,MEM_DECOMMIT);
  readln;
end.

Es reicht fürs erste sicherlich aus dem Wort Variable in deinem Tut "Konstante" zu machen Für die Einführung in asm würde alles weitere nur verwirren.


Edit: Wie langweilig, wäre doch das Leben ohne Fehler; Ich habe mal eine sinnlose Variable aus dem zweiten CodeSchnippsel von mir entfernt.
Edit2: Fehler über Fehler (im code zum ändern von add und sub)
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat