Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Assemler Routine ummodeln - wer kann bitte helfen (https://www.delphipraxis.net/101034-assemler-routine-ummodeln-wer-kann-bitte-helfen.html)

turboPASCAL 7. Okt 2007 13:48


Assemler Routine ummodeln - wer kann bitte helfen
 
Hi,

ich habe volgende Procedure:

Delphi-Quellcode:
{------------------------------------------------------------------}
{  Swap bitmap format from BGR to RGB                             }
{------------------------------------------------------------------}
procedure SwapRGB(data : Pointer; Size : Integer);
asm
  mov ebx, eax
  mov ecx, size

@@loop :
  mov al,[ebx+0]
  mov ah,[ebx+2]
  mov [ebx+2],al
  mov [ebx+0],ah
  add ebx,3
  dec ecx
  jnz @@loop
end;
und möchte sie wiefolgt verändern:

Delphi-Quellcode:
procedure SwapRGB(data : Pointer; Size : Integer; Step: Byte);
asm
  mov ebx, eax
  mov ecx, size
  mov ???, step

@@loop :
  mov al,[ebx+0]
  mov ah,[ebx+2]
  mov [ebx+2],al
  mov [ebx+0],ah
  add ebx, ??? (4)
  dec ecx
  jnz @@loop
end;
Das soll ein Array umformen in etwa so:

Code:
BGRA, BGRA, BGRA...
// nach:
RGBA, RGBA, RGBA...

und das ergibt dann eine Bitmapladeroutiene für zB. OpenGl:

Delphi-Quellcode:
function LoadBMPTexture(ResID: Integer; var Texture : GLuint) : Boolean;
var
  BitmapLength: LongWord;
  bmpBits: array of byte;
  hBmp: HBitmap;
  bi: tagBITMAP;
begin
  hBmp := Loadimage(HInstance, MAKEINTRESOURCE(ResID), IMAGE_BITMAP, 0,0,0);
  GetObject(hBmp, sizeof(bi), @bi);
  BitmapLength := bi.bmWidth * bi.bmHeight * bi.bmBitsPixel Div 8;
  SetLength(bmpBits, BitmapLength+1);
  GetBitmapBits(hBmp, BitmapLength, @bmpBits[0]);

  if @bmpBits[0] <> nil then
  begin
    SwapRGB(@bmpBits[0], bi.bmWidth * bi.bmHeight);  // Swap Bitmap Bits BGR(A) to RGB(A)
    Texture := CreateTexture(bi.bmWidth, bi.bmHeight, GL_RGBA, @bmpBits[0]);
    Result := (Texture <> 0);
  end else
    Result := False;

  DeleteObject(hBmp);
end;

kolbaschedder 7. Okt 2007 13:54

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Hallo,

wenn ich das richtig verstehe, macht das die vorhandene Funktion bereits.
Delphi-Quellcode:
  dec ecx <-- size um 1 erniedrigen
  jnz @@loop <--jnz = jump if not zero, also springe nach @@loop wenn size noch nicht null
MfG

Kolbaschedder

sirius 7. Okt 2007 13:55

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Also:
1. Diese Routine ist ganz gefährlich, da sie ebx verändert und nicht zurücksetzt!
Bsp: Falls du sie aus einer längeren Methode aufrufst (Delphi legt self meist in ebx) wird self verändert du hast einen fehler beim Zugriff auf Objekteigene Properties etc. Auch sonst kann etwas wichtiges in ebx liegen, was die aufrufende Routine gerne so wieder vorfinden möchte. Hingegen darf eax, ecx und edx verändert werden.
2. wäre ja noch edx frei, da muss ich mal schauen. Warum willst du es eigentlich in Assembler?

Edit: und 3. Was soll jetzt step bei dir bzw. dem Beispiel bewirken?

sirius 7. Okt 2007 14:05

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Ich glaube, ich weis jetzt, was du meinst.
Für deinen Fall müsstest du in step 1 übergeben.
Delphi-Quellcode:
procedure SwapRGB(data : Pointer; Size : Integer; Step: Integer);
asm
  push ebx
  add ecx,3
  test edx,edx
  jz @@end

@@loop :
  mov bl,[eax+0]
  mov bh,[eax+2]
  mov [eax+2],bl
  mov [eax+0],bh
  add eax, ecx
  dec edx
  jnz @@loop
@@end:
  pop ebx
end;

turboPASCAL 7. Okt 2007 14:29

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Tja, nun steig ich nicht mehr so recht druch. wo werden denn
die Parameter wie step übergeben (an den asm-Teil)?

Apollonius 7. Okt 2007 14:32

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Aufrufkonvention ist Register, folglich liegt Data in EAX, Size in EDX und Step in ECX.

turboPASCAL 7. Okt 2007 15:03

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
thx Apollonius.


Also nochmal für Dummies, wie müsste folgender Code als ASM aussehen ?

Delphi-Quellcode:
 // pData als Pointer übergeben ?!... (to do...)

  procedure _SwapRGB(pData: TByteArray; pDataLength: DWORD; Alpha: Byte);
  var
    n: DWORD;
    b, r: byte;
  begin
    n := 0;
    while n <= pDataLength-4 do
    begin
      b := pData[n];
      r := pData[n + 2];
      pData[n] := r;
      pData[n + 2] := b;
      pData[n + 3] := Alpha;
      inc(n, 4);
    end;
  end;

oder macht das keinen Sinn für die Geschwindigkeit (Delphi oder ASM)

sirius 7. Okt 2007 15:11

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Wenn es einen Unterschied gibt, dann dürfte er sehr gering sein.

turboPASCAL 7. Okt 2007 15:19

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Bei grossen Bitmaps (1024*1024) scheint es noch recht zügig zu laufen. :gruebel:

sirius 7. Okt 2007 15:35

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Kannst ja die probieren:
Delphi-Quellcode:
procedure SwapRGB(data : Pointer; Size : Integer; Alpha:byte);
asm
  push ebx
  test edx,edx
  jz @@end

@@loop :
  mov bl,[eax+0]
  mov bh,[eax+2]
  mov [eax+2],bl
  mov [eax+0],bh
  mov [eax+3],cl

  add eax, 4
  sub edx, 4
  jnle @@loop
@@end:
  pop ebx
end;

OldGrumpy 7. Okt 2007 16:30

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Zitat:

Zitat von turboPASCAL
Hi,

ich habe volgende Procedure:

Delphi-Quellcode:
{------------------------------------------------------------------}
{  Swap bitmap format from BGR to RGB                             }
{------------------------------------------------------------------}
[...]
  add ebx,3
[...]
und möchte sie wiefolgt verändern:
[...]
Das soll ein Array umformen in etwa so:

Code:
BGRA, BGRA, BGRA...
// nach:
RGBA, RGBA, RGBA...
[...]

Abgesehen von allen anderen Kommentaren: Deine ursprüngliche Routine setzte 24 Bit pro Pixel (je 8 für R,G,B) voraus, Du hättest gerne 32 pro Pixel. Alles was dazu notwendig ist, ist die Schleife statt in 3er-Schritten in 4er-Schritten laufen zu lassen. Statt add ebx,3 also einfach add ebx,4 und fertig. Nichtsdestotrotz sind alle restlichen Warnungen bzgl. EBX=self etc. zu beherzigen :)

turboPASCAL 7. Okt 2007 16:55

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
@sirius, das tut das was es soll. :thumb:

Es währe noch nett wen mir das jemand kommentiert bis auf die mov ...,... da seh ich durch.
Aber sonst :gruebel:

@OldGrumpy,
Zitat:

Deine ursprüngliche Routine setzte 24 Bit pro Pixel [...]
Alles was dazu notwendig ist, ist die Schleife statt in 3er-Schritten in 4er-Schritten laufen zu lassen
Ja, wenn man weis wie ... ;)

Apollonius 7. Okt 2007 17:04

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Delphi-Quellcode:
procedure SwapRGB(data : Pointer; Size : Integer; Alpha:byte);
asm
  push ebx //ebx sichern
  test edx,edx //Wenn Größe=0, Abbruch
  jz @@end

@@loop :
  mov bl,[eax+0] //R holen
  mov bh,[eax+2] //B holen
  mov [eax+2],bl //und tauschen
  mov [eax+0],bh
  mov [eax+3],cl //den Alpha-Wert speichern

  add eax, 4 //die nächsten vier Byte
  sub edx, 4 //Size:=Size-4
  jnle @@loop //Müssen wir nochmal?
@@end:
  pop ebx //ebx zurückholen
end;

turboPASCAL 7. Okt 2007 17:48

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Ja, danke. :thumb:

Wo kann man so ein Zeugs nachlesen ? :gruebel:

sirius 7. Okt 2007 18:02

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Wahrscheinlich in Büchern :zwinker:

Was willst du denn nachlesen? Also ASM in Delphi ist recht einfach. Die Anzahl der Befehle in ASM sind ja recht übersichtlich (und gibts hier und da im Internet oder im Buch).
Um alle anderen Sachen (Stack einrichten etc.) muss man sich ja unter Delphi nicht mehr kümmern. Das zum Thema ASM benutzen.
(ich habe übrigens nur im Internet nachgelesen und besitze kein Buch)

Jetzt zum besonderen von ASM unter Delphi:
du musst dich eben ein wenig mit dem Compiler arrangieren (z.B. das Wissen wie delphi die Parameter übergibt etc.). Dazu hat balu der Bär mal ein TUT geschrieben.
Edit: Das tut ist hier

Apollonius 7. Okt 2007 18:20

Re: Assemler Routine ummodeln - wer kann bitte helfen
 
Ich habe mir das "Zeugs" im Frühjahr angeeignet, ebenfalls nur aus dem Internet. Ungemein geholfen hat es mir, dass beim kostenlsoen Delphi 2005 die Quellcodes der Standardunits nicht dabei sind. Wenn man da wissen will, wie etwas gemacht wird, hilft nur noch eine gute Assembler-Kenntnis. Ich habe da wirklich Stunden daran gesessen, herauszufinden, wie der Aufruf von dynamischen Methoden erfolgt - und nebenbei noch herauszuarbeiten, wie die DMT denn aussieht.
Kurz gesagt gilt auch hier: Übung macht den Meister.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:22 Uhr.

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