Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Fehler beim Byte-Swap mit Assembler in Delphi (https://www.delphipraxis.net/48884-fehler-beim-byte-swap-mit-assembler-delphi.html)

turboPASCAL 1. Jul 2005 21:39


Fehler beim Byte-Swap mit Assembler in Delphi
 
Delphi-Quellcode:
function SwapDWord(DW: DWord): DWord;
begin
  asm
    mov  eax, [DW] // Register EAX mit Wert von DW füllen // <- ... Inline Assembler Syntaxfehler
    bswap eax      // Byte-Swap durchfhüren
    mov  [DW], eax // Wert aus EAX zurück nach DW schreiben
  end;
  Result := DW;
end;
Mein Assembler ist ziemlich Eingerostet, das sollte aber doch so stimmen oder ?

Phistev 1. Jul 2005 21:44

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Beschäftige dich mit der Aufrufkonvention register (1. Parameter in EAX, Rückgabe in EAX glaub' ich zumindestens) :zwinker:

Olli 1. Jul 2005 21:48

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Delphi-Quellcode:
function SwapDWord(DW: DWord): DWord;
asm
  bswap eax      // Byte-Swap durchführen
end;
Viel Spaß ;)

Und wenn wir schon dabei sind: [DW] wäre die Adresse auf welche DW zeigt. Und zwar das DWORD an dieser Stelle, weil der Zieloperand die Größe vorgibt ;)

Ach ja und Delphi 4 kennt z.B. noch nicht BSWAP. Da heißt es dann:

Delphi-Quellcode:
function SwapDWord(DW: DWord): DWord;
asm
  db   0Fh, 0C8h      // "bswap EAX" can only be executed on 486+!!!
end;
So habe ich es bei der Native API-Unit der JEDIs gelöst:
Delphi-Quellcode:
(* Own function to swap bytes in 32bit values

   The RtlUlongByteSwap routine converts a ULONG from little-endian to
   big-endian, and vice versa. *)
function RtlUlongByteSwap(Source:ULONG):ULONG;
asm
  // This is not written as mnemonics to be compatible with D4!
  db   0Fh, 0C8h      // "bswap EAX" can only be executed on 486+!!!
(*
// Does the same but perhaps slower ...
                        // Source = $11223344
  rol  AX, 08h       // Source = $11224433
  rol  EAX, 0Fh       // Source = $44331122
  rol  AX, 08h       // Source = $44332211
*)
end;

Olli 1. Jul 2005 21:56

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Falls du es noch für ULONGLONG (LARGE_INTEGER/ULARGE_INTEGER) brauchst:

Delphi-Quellcode:
(* Own function to swap bytes in 64bit values

   The RtlUlonglongByteSwap routine converts a ULONGLONG from
   little-endian to big-endian, and vice versa. *)
function RtlUlonglongByteSwap(Source:ULONGLONG):ULONGLONG;
asm
  mov  EAX, [ESP+0Ch] // Get the high part of the ULONGLONG into EAX
  mov  EDX, [ESP+08h] // Get the low part of the ULONGLONG into EDX
  // This is not written as mnemonics to be compatible with D4!
  db   0Fh, 0C8h      // "bswap EAX" can only be executed on 486+!!!
  db   0Fh, 0CAh      // "bswap EDX" can only be executed on 486+!!!
  // High part returns in EDX, low part in EAX
end;
Ach Quark ... für die Vollständigkeit noch 16bit-Werte:

Delphi-Quellcode:
(* Own function to swap bytes in 16bit values

   The RtlUshortByteSwap routine converts a USHORT from
   little-endian to big-endian, and vice versa. *)
function RtlUshortByteSwap(Source:USHORT):USHORT;
asm
  rol  AX, 08h
end;
Ach ja, der Code ist JEDI-kompatibel unter MPL. Aber da ich der Urheber bin ;) ...

turboPASCAL 1. Jul 2005 21:59

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Delphi-Quellcode:
function SwapDWord(DW: DWord): DWord;
asm
  bswap eax      // Byte-Swap durchführen
end;
Hatte ich gerade so, dachte man muss erst etwas zuweisen.

muss man also z.B. so sreiben:
Delphi-Quellcode:
// summe = summe + Value;

add eax, [Value]
// oder so?
add eax, Value

Olli 1. Jul 2005 22:04

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Zitat:

Zitat von turboPASCAL
Delphi-Quellcode:
// summe = summe + Value;

add eax, [Value]
// oder so?
add eax, Value

Das kommt immer darauf an. Wenn Value als var/const übergeben wird, kann das sein.

Delphis register ist fast wie __fastcall in C. Der erste Wert kommt in EAX, der zweite in ECX, der dritte in EDX, der Rest auf dem Stack, wenn ich nicht irre. Außerdem werden 32bit-Werte in EAX übergeben. 64bit in EAX:EDX.
Reihenfolge nachträglich korrigiert!

Die OH sagt dazu:
You can write complete procedures and functions using inline assembler code, without including a begin...end statement. For example,

Delphi-Quellcode:
function LongMul(X, Y: Integer): Longint;   

asm
  MOV    EAX,X
  IMUL   Y
end;
The compiler performs several optimizations on these routines:

No code is generated to copy value parameters into local variables. This affects all string-type value parameters and other value parameters whose size isn’t 1, 2, or 4 bytes. Within the routine, such parameters must be treated as if they were var parameters.
Unless a function returns a string, variant, or interface reference, the compiler doesn’t allocate a function result variable; a reference to the @Result symbol is an error. For strings, variants, and interfaces, the caller always allocates an @Result pointer.

The compiler generates no stack frame for routines that aren’t nested and have no parameters or local variables.
The automatically generated entry and exit code for the routine looks like this:

Delphi-Quellcode:
PUSH   EBP             ;Present if Locals <> 0 or Params <> 0

MOV    EBP,ESP         ;Present if Locals <> 0 or Params <> 0
SUB    ESP,Locals      ;Present if Locals <> 0
 ...
MOV    ESP,EBP         ;Present if Locals <> 0
POP    EBP             ;Present if Locals <> 0 or Params <> 0
RET    Params          ;Always present
If locals include variants, long strings, or interfaces, they are initialized to zero but not finalized.

Locals is the size of the local variables and Params is the size of the parameters. If both Locals and Params are zero, there is no entry code, and the exit code consists simply of a RET instruction.

Assembler functions return their results as follows.

Ordinal values are returned in AL (8-bit values), AX (16-bit values), or EAX (32-bit values).
Real values are returned in ST(0) on the coprocessor’s register stack. (Currency values are scaled by 10000.)
Pointers, including long strings, are returned in EAX.
Short strings and variants are returned in the temporary location pointed to by @Result.

turboPASCAL 1. Jul 2005 22:08

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Super, Danke!

Richtige Profis hier !

Robert Marquardt 2. Jul 2005 05:23

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Das mit dem BSWAP alleine funktioniert nicht wenn man die Optimierung ausschaltet und die Stackframes ein (beispielsweise fuer Debugging).
Der Compiler laesst es naemlich dann mit der Register-Calling-Convention sein und der erste Parameter steht nicht mehr in EAX.

Die Jedi-Funktionen (aus der jedi-apilib) wandern demnaechst in die JCL wo sie hingehoeren.

Olli 2. Jul 2005 09:11

Re: Fehler beim Byte-Swap mit Assembler in Delphi
 
Zitat:

Zitat von Robert Marquardt
Das mit dem BSWAP alleine funktioniert nicht wenn man die Optimierung ausschaltet und die Stackframes ein (beispielsweise fuer Debugging).
Der Compiler laesst es naemlich dann mit der Register-Calling-Convention sein und der erste Parameter steht nicht mehr in EAX.

:shock: ... muß man denen wohl immer explizit register hintanstellen oder was? Kann ich mir eigentlich nicht vorstellen, weil's für den Debugger keinen Vorteil bringt. Ich bitte um PM zum Thema, damit ich einen Bugfix erarbeiten und einchecken kann.

Zitat:

Zitat von Robert Marquardt
Die Jedi-Funktionen (aus der jedi-apilib) wandern demnaechst in die JCL wo sie hingehoeren.

Watt? :shock: Wieso? Häh? Das sind doch 2 komplett verschiedene Projekte.

x000x 28. Feb 2012 09:20

AW: Fehler beim Byte-Swap mit Assembler in Delphi
 
Moin moin,

ich hol den Thread hier mal aus der Versendkung...
Wie sieht es mit der Funktion unter XE2 aus => Funktioniert diese unter einem 64bit noch genauso bzw. was muss geändert werden?
Delphi-Quellcode:
function SwapDWord(DW: DWord): DWord;
asm
  bswap eax // Byte-Swap durchführen
end;
(Ich kann es nicht selber testen und habe dazu noch wenig Ahnung von ASM)


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:52 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz