![]() |
Byte an bestimmter Speicherposition mit Assembler löschen
Wäre wirklich schön, wenn mir damit jemand helfen könnte, der sich besser damit auskennt.
Ich habe mich mal daran gemacht einige Assemblerfunktionen zu schreiben, um ein wenig dazuzulernen, ob asm bei so etwas sinnvoll ist, sei mal dahin gestellt. Folgende Funktion soll zusammenhängendes Byte einer Variable oder Instanz löschen (mit 0 füllen).
Delphi-Quellcode:
Das Ganze funktioniert so weit auch ganz gut, meine Frage ist mehr, ob diese Lösung effektiv ist, oder wie "der übliche Weg" für so etwas aussieht (ohne im Pointer gleich den Anfang des zu löschenden Bytes zu übergeben). asm wird ja normalerweise nur benutzt, um Code möglichst effektiv zu gestalten.
procedure ByteLoeschen(p: Pointer; Index: Byte); assembler;
asm mov EDX, 0FFFFFF00h mov CL, BL sal Cl, 3 //Linksverschiebung mit Anhängen von Nullen, *2*2*2 STC //setze Carry-Flag, um kein Bit zu verlieren rcl EDX, CL //Rechtsverschuebung mit Anhängen des Carry-Flags, setzt Carry-Flag and [EAX], EDX end; |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Also wenn du ein Byte an einer bestimmten Speicherstelle löschen willst, warum benutzt du dann nicht einfach mov dword ptr eax, 0?
|
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Wohl eher Byte ptr eax.
@CyF: Funktioniert das? Der zweite Parameter liegt in dl, nicht bl. |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hab die ganze Teit eine Methode gesucht was anderes als 32-Bit Blöcke zu schreiben und hab eine Möglichkeit gesucht es trotzdem zu schaffen... hmm naja, warum auch einfach. :wink:
Habs mal so ersetzt:
Delphi-Quellcode:
Dabei scheint es erstaunlicherweiße egal zu sein, ob ich EBX oder EDX nehme, funktioniert beides, was mich etwas verwirrt.
procedure ByteLoeschen2(p: Pointer; Index: Byte); assembler;
asm mov Byte [EAX + EBX], 0 end; Man sollte aber normalerweiße das 'D'-Register für das 2te Argument nehmen? Was genau ist mit 'prt' eax gemeint? |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Natürlich, byte ptr, ich war jetzt irgendwie auf Cardinal...
byte ptr heißt einfach, dass man nicht in EAX schreibt, sondern auf das Byte, das EAX referenziert. |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Kannst du mal zeigen, wie du deine Funktion aufrufst? Denn EBX zu verwenden ist garantiert falsch.
BYTE PTR EAX ist das selbe wie [EAX], nur das zusätzlich klargestellt wird, dass EAX auf ein Byte und nicht etwa auf ein Word, Dword oder sonstiges zeigt. |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hier mal der Quelltext der ganzen Unit:
Delphi-Quellcode:
Wenn dadurch klar wird, warum der zweite Parameter auch in EBX liegt, lasst es mich wissen.
unit Main;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) BLoeschen: TButton; EZahl: TEdit; EZahlHex: TEdit; EGeloescht: TEdit; EGeloeschtHex: TEdit; LByte: TLabel; EByte: TEdit; procedure BLoeschenClick(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; procedure ByteLoeschen(p: Pointer; Index: Byte); procedure ByteLoeschen2(p: Pointer; Index: Byte); var Form1: TForm1; implementation procedure ByteLoeschen(p: Pointer; Index: Byte); assembler; asm mov EDX, 0FFFFFF00h mov CL, BL sal Cl, 3 //Linksverschiebung mit Anhängen von Nullen, *2*2*2 STC //setze Carry-Flag, um kein Bit zu verlieren rcl EDX, CL //Rechtsverschuebung mit Anhängen des Carry-Flags, setzt Carry-Flag and [EAX], EDX end; procedure ByteLoeschen2(p: Pointer; Index: Byte); assembler; asm mov Byte [EAX + EBX], 0 end; {$R *.dfm} procedure TForm1.BLoeschenClick(Sender: TObject); var IntZahl: Integer; ByteNr: Shortint; begin try IntZahl:= StrToInt(EZahl.Text); ByteNr:= StrToInt(EByte.Text) - 1; if((IntZahl < 0) or (ByteNr < 0) or (ByteNr > 3)) then begin raise Exception.Create('Ungültiger Wert!'); end; EZahlHex.Text:= IntToHex(IntZahl, 1); ByteLoeschen2(@IntZahl, ByteNr); EGeloescht.Text:= IntToStr(IntZahl); EGeloeschtHex.Text:= IntToHex(IntZahl, 1); except ShowMessage('Ungültiger Wert!'); end; end; end. |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hallo Cyf,
die Register EAX, ECX und EDX stehen unter Delphi zur freien Verfügung. Willst Du die anderen Register verwenden, so sollte man sie vor der Veränderung auf den Stack packen und vor dem Verlassen in den ursprünglichen Zustand wieder herstellen. Bis bald Chemiker |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Delphi-Quellcode:
Funktionen sind nun so verändert, dass sie EBX nicht mehr verwenden (auch wenn keine Veränderung erfolgte).
procedure ByteLoeschen(p: Pointer; Index: Byte); assembler;
asm mov CL, DL mov EDX, 0FFFFFF00h sal Cl, 3 //Linksverschiebung mit Anhängen von Nullen, *2*2*2 STC //setze Carry-Flag, um kein Bit zu verlieren rcl EDX, CL //Rechtsverschuebung mit Anhängen des Carry-Flags, setzt Carry-Flag and [EAX], EDX end; procedure ByteLoeschen2(p: Pointer; Index: Byte); assembler; asm mov Byte [EAX + EDX], 0 end; Jemand eine Idee, warum EBX den selben Wert wie EDX enthielt (2. Parameter)? (nur aus meiner Neuier herraus :wink: ) |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Schau doch einfach mal in der CPU-Ansicht nach.
|
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hallo Cyf,
das wird wahrscheinlich reiner Zufall sein. Bis bald Chemiker |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Code:
:wall: Das mit der CPU war eine gute Idee, hätte eigentlich gleich den Debugger mal fragen sollen.
Main.pas.61: ByteLoeschen2(@IntZahl, ByteNr);
00459861 8D45FC lea eax,[ebp-$04] 00459864 8BD3 mov edx,ebx 00459866 E84DFFFFFF call ByteLoeschen2 Der obige Aufrufcode sollte das ja erklären. Danke für die Hilfe. :thumb: |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
davon abgesehen dass man direkt nen PByte(bla)^ := 0 machen kann (sofern bla dann schon an der richtigen stelle ist)
warum nicht:
Delphi-Quellcode:
?
procedure ByteLoeschen(p: Pointer; Index: Integer);
asm MOV BYTE PTR [EAX+EDX], 0 end; ops gerade erst gesehen dass du das schon hast :) |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Guten Morgen :-D ,
ich möcht' nur noch eine kleine Anmerkung machen: ich programmier' selber gern in Assembler und in meinen Programmen/Units geb' ich die Übergabekonvention immer explizit an, also (assembler;register;).
Delphi-Quellcode:
Bei maximal 3 Übergabeparametern ist 'register' zwar die Standardübergabekonvention (zumindest bei meinem Delphi 4 :oops:), die explizite Angabe bewahrt mich aber ganz sicher vor Überraschungen.
Procedure SetZero(P:Pointer;Index:Integer);assembler;register;
ASM mov Byte Ptr [eax+edx],0 END; Einen schönen Tag noch Laplace |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Bei der Gelegenheit wäre vielleicht auch eine Auflistung aller Übergabekonventionen noch mal intressant, konnte aber per Suche keine finden, sind zumindest diese jetzt so korrekt?
register : Die ersten drei Argumente der Reihenfolge nach in EAX, EDX und ECX, ggf. die Restlichen auf dem Stack Zitat:
stdcall: Alle Argumente auf dem Stack, auch hier wieder je weiter hinten, desto weiter "unten" Es gibt noch CDecl, aber wie sie da angeordnet sind bin ich nicht sicher. Wäre eventuell sinnvoll, das in einem extra Thema mal zu sammeln, weil das sicher immer mal wieder intresannt sein kann. (auch z.B. für dll s) [EDIT] Fehler beseitigt, nicht das es hier wer falsch liest. :stupid: |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hi,
Zitat:
Aus der D7-Hilfe: Zitat:
Zitat:
Mfg FAlter |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Die fünf in Delphi verfügbaren Aufrufkonventionen sind in der Delphi-Hilfe und bei
![]() CyFs Beschreibung von Register ist nicht ganz korrekt: Der erste Parameter von links, der auf den Stack geschoben wird, wird im Gegensatz zu CDecl, StdCall und Safecall als erstes auf den Stack geschoben und liegt damit, wie übrigens auch bei Pascal, zuunterst. @Laplace: Die Standard-Aufrufkonvention ist unabhängig von der Parameteranzahl und der Delphi-Version immer Register. |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hallo Appolonius :hi:,
soweit ich weiß, sind (zumindest in D4) nur EAX, EDX und ECX in Assembler frei verfügbar. Wenn du mehr als 3 Parameter übergeben willst, reichen die Register also (alleine) nicht aus. Hallo FAlter :) , die angegebene Syntax (assembler;register) stammt aus dem Handbuch für Delphi 4. Mag bei anderen Compilerversionen unterschiedlich sein. Aber danke für deinen Hinweis :P . Schönen Abend noch Laplace |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hallo Laplace,
das ist natürlich richtig. Doch zur Aufrufkonvention Register gehört eben auch, dass überzählige Parameter in der Reihenfolge der Deklaration auf den Stack gepusht werden. Nur weil es zu viele (oder zu große) Parameter sind, wird also nicht plötzlich die Aufrufkonvention StdCall verwendet. Grüße Apollonius |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hallo Appolonius :-D ,
weiß schon. Bei mir ist's so, dass immer wenn ich eine interne Funktion bzw. Prozedur mit max. 3 Parametern aufrufen/schreiben kann, dann juckt's mich, das in assembler zu schreiben - hauptsächlich bei Stringoperationen. Maximal 3 Parameter halte ich für (interne) Assemblerroutinen als fast optimal. Ansonsten ist mir das eher zu 'unübersichtlich' und weiche (nur) notfalls auf die Deklaration 'pascal' aus. Schönen Abend noch Laplace |
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Wieso verwendest du denn überhaupt Pascal und nicht immer Register?
|
Re: Byte an bestimmter Speicherposition mit Assembler lösche
Hallo Apollonius :hi:,
bei der Aufrufkonvention 'pascal' sind für mich die Verhältnisse klarer. Bei 'register' werden die ersten 3 Parameter über eax, edx, ecx übergeben, der Rest über den Stack (siehe Cyf's post oben). Da ich manchmal die Übergabeparameter (Anzahl und/oder Reihenfolge) im Laufe der Programmierung einer Prozedur/Funktion noch ändere :oops:, müßte ich in diesem Fall darauf achten, an welcher Position ein bestimmter Parameter übergeben wird. Dazu bin ich zu bequem (= zu faul :mrgreen:). Bei der Konvention 'pascal' ist der Zugriff einheitlich über den Stack :thumb:. Schönen Tag noch Laplace P.S. Übrigens: Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz