Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Rgb mittels Asm darstellen (https://www.delphipraxis.net/133524-rgb-mittels-asm-darstellen.html)

thomasku 4. Mai 2009 00:42


Rgb mittels Asm darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

Ich möchte gern die rgb Funktion mittels assemblercode darstellen.
Delphi-Quellcode:
function farbverlauf1(rot,gruen:integer):TColor;
begin
  if rot < gruen then
    result:=rgb(rot-gruen,0,0)
  else
    result:=rgb(0,gruen-rot,0);
{$R *.dfm}
end;
function farbverlauf2(rot,gruen:integer):TColor;
begin
  ASM
    Mov Eax,rot;     //init
    Mov Edx,gruen;
    CMP Eax,edx;
    jns @kalt;       //rot<gruen
    sub edx,eax;
    Mov result,Eax;
    jmp @weiter;
    @kalt:
      sub edx,eax;
      shl eax,8;
      Mov result,Eax;
    @weiter:
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
Var x,y:integer;
begin
  For x:=0 to 255 do
    For y:=0 to 255 do
      Image1.Canvas.Pixels[x,y]:=farbverlauf2(x,y);
      Image1.Update;
end;
MIt dieser bekomme ich zwar ein ähnliches Ergebnis, allerdings dunkler(wobei beides integer, a 8 Bit sind).
Siehe dazu Bild.
Folgende Funktion hatte ich ursprünglich, hier erhalte ich aber nur einen teil.
Delphi-Quellcode:
function farbverlauf2(rot,gruen:integer):TColor;
begin
  ASM
    Mov Eax,rot;     //init
    Mov Edx,gruen;
    CMP Eax,edx;
    jns @kalt;       //rot<gruen
    sub eax,edx;
    Mov result,Eax;
    jmp @weiter;
    @kalt:
      sub edx,eax;
      shl eax,8;
      Mov result,Eax;
    @weiter:
  end;
end;
Mfg thomas

Medium 4. Mai 2009 04:11

Re: Rgb mittels Asm darstellen
 
Ohne jetzt explizit auf das Problem einzugehen: Wenn es dir hierbei um einen Geschwindigkeitsvorteil geht (und 8 Bit/Kanal ausreichen), sollte es sich für dich lohnen wenn du dir den MMX Befehlssatz mal anschaust.
Mir ist ausserdem gerade schleierhaft inwiefern deine Farbverlaufsmethode sinnvoll eingesetzt werden könnte - darf man fragen wozu du sie brauchst? (Reines Interesse, keine subtile Kritik.)

thomasku 4. Mai 2009 04:23

Re: Rgb mittels Asm darstellen
 
Hallo Medium und vielen Dank,

Nein um Geschwindigkeit oder irgendeinen anderen multimedialen Einsatz geht es mir nicht.
Die Aufgabe habe ich in dieser Art gestellt bekommen. Der Sinn ist die Einbindung von Assemblerbefehlen in Delphi.
Dienen soll es der Darstellung von Temperaturen, rot=warm...

Mfg thomas

Medium 4. Mai 2009 04:27

Re: Rgb mittels Asm darstellen
 
Ahhhh okay, danke :)
Was das Problem an sich angeht... da hätte ich wohl die Nacht besser nicht durchgemacht *hust* :stupid: Ich seh nur noch Matsche aufm Bildschirm, au ha.

jaenicke 4. Mai 2009 05:38

Re: Rgb mittels Asm darstellen
 
Was mir auffällt ist erst einmal: Wozu legst du die Parameter in eax und edx? Da sind die doch eh schon drin...
Mach lieber eine komplette Assemblerroutine draus, dann sparst du dir das.

Zum Fehler:
Delphi-Quellcode:
sub edx,eax;
    Mov result,Eax;
Du subtrahierst von edx (gruen) den Inhalt von eax (rot), also gruen - rot, und das ist dann in edx. Danach packst du den Inhalt von eax (rot) in Result... ;-)
Du hast die Parameter für sub vertauscht. Vor allem machst du ja die selbe Subtraktion für beide Fälle und benutzt danach immer das (unveränderte) eax.

thomasku 4. Mai 2009 06:57

Re: Rgb mittels Asm darstellen
 
Morgen jaenicke und vielen Dank,

Hatte schon im ersten Post sowie in meinem Programm einen Fehler.
rot < gruen => rot>gruen

und mit deinen Tipps, habe ich nun auch das selbige raus.
vollstaendigkeits- halber der Code:
Delphi-Quellcode:
function farbverlauf1(rot,gruen:integer):TColor;
begin
  if rot > gruen then
    result:=rgb(rot-gruen,0,0)
  else
    result:=rgb(0,gruen-rot,0);
{$R *.dfm}
end;
function farbverlauf2(rot,gruen:integer):TColor;
begin
  ASM
    Mov Eax,rot;     //init
    Mov Edx,gruen;
    CMP Eax,edx;
    js @kalt;       //rot<gruen
    sub eax,edx;
    Mov result,Eax;
    jmp @weiter;
    @kalt:
      sub edx,eax;
      shl edx,8;
      Mov result,Edx;
    @weiter:
  end;
end;
Momentan sehe ich zwar noch nicht warum ich nicht die selbe Grafik erhalte, wenn ich wie oben, in farbverlauf1 das Relationszeichen drehe und in farbverlauf2 aus js =>jns mache, allerdings bin ich erstmal sehr froh das es klappt. :lol:

Ich habe keine eigene Routine gemacht, weil ich noch nicht weiß wie dies geht. Ich mache derzeit meine ersten Gehversuche mit der Assemblereinbindung.

Mfg thomas

jaenicke 4. Mai 2009 07:04

Re: Rgb mittels Asm darstellen
 
Schreib das einfach so:
Delphi-Quellcode:
function farbverlauf2(rot, gruen: integer): TColor;
asm
  cmp eax, edx;
  js @kalt;       //rot<gruen
  sub eax, edx;
  jmp @weiter;
  @kalt:
    sub edx, eax;
    shl edx, 8;
    mov eax, edx;
  @weiter:
end;
Die Parameter liegen der Reihe nach in EAX, EDX und ECX, danach auf dem Stack. Das Ergebnis gehört in EAX.

(Ausnahme wäre ein String als Rückgabewert. Dabei wird der String für das Ergebnis wie ein weiterer Parameter übergeben.)

thomasku 4. Mai 2009 07:17

Re: Rgb mittels Asm darstellen
 
Danke nochmal,

Achso dann muss ich wohl leider zugeben, dass ich doch schon einmal etwas davon gehört habe.
(Mit Stackframe bzw ohne, dachte immer mit ist die sichere Variante)
Ich werde mich nochmal intensiver damit beschäftigen.

Mfg thomas

himitsu 4. Mai 2009 08:28

Re: Rgb mittels Asm darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Delphi-Quellcode:
function farbverlauf2(rot,gruen:integer):TColor;
begin
  ASM
    @kalt:
      sub edx,eax;
erstmal das Begin-End ... darum wird doch bestimmt ein "unnötiger" Stackframe erstellt
und durch die nutzung von Result (mittendrin) ebenfalls ... dort wird Result<>EAX bestimmt sein, da zwischendurch eine Temp-Variable für Result eingerichtet und diese erst am Ende nach EAX kopiert wird.

außerdem wozu rechnest du da mit EDX, wo du EDX danach eh nichtmehr verwendest?
bei kalt also überall statt eax ein edx verwenden :zwinker:

und wenn das ASM richtig genutzt würde (ohne delphis Stackframe), dann wäre Mov result,Eax; eh "nutzlos", da Result=EAX.

also ich würde mal stark vermuten, daß 'ne compileroptimierte Variante am Ende sogar schneller/optimaler arbeitet, als dieser ASM-Code.
[add] *ins Bild guck* ... stümmt [/add]

PS: jns @kalt;
im High-Byte ist ein Steurbyte (bei der GDI für die verwendete Farboalette) und keine der Farben Rot oder Grün, also hat dieser Vergleich nichts mit Rot-Grün zu tun.

oben im Bild:
Delphi-Quellcode:
function farbverlauf2(rot, gruen: Integer): TColor;
begin
  if rot < gruen then result := rot - gruen
  else result := (gruen - rot) shl 8;
end;
unten im Bild:
Code:
[b]function[/b] farbverlauf2(rot,gruen:integer):TColor;
[b]begin[/b]
  [b]ASM[/b]
    Mov Eax,rot     //init
    Mov Edx,gruen
    CMP Eax,edx
    jns @kalt      //rot<gruen
    sub eax,edx
    Mov result,Eax
    jmp @weiter
    @kalt:
      sub edx,eax
      shl [color=#ff0000]edx[/color], 8
      Mov result, [color=#ff000]Edx[/color]
    @weiter:
  [b]end;[/b]
[b]end;[/b]
und in einem "neueren" Delphi, wo Inline-Funktionen unterstütz werden, wäre dieses das optimalste, da dort nichtmal erst 'ne Funktion angelegt, sondern der Code direkt an der aufrufenden Stelle eingefügt würde. :angel:
Delphi-Quellcode:
function farbverlauf2(rot, gruen: Integer): TColor; Inline;
begin
  if rot < gruen then result := rot - gruen
  else result := (gruen - rot) shl 8;
end;
[edit]
ups, Bild vergessen :oops:

[add]
und wenn ich mir den Code von jaenicke anseh ... bis auf jmp @weiter;, welches in 'ner kleinem RET kürzer wär ... ist's schonmal ein sehr großer Fortschritt, gegenüber dem "Original" :angel2:


[add2]
was du eigentlich meintest war:
(sobald du für rot und gruen mal 'nen Wert außerhalb von 0..255 übergibst, wirst du den Unterschied erkennen :wink: )
Delphi-Quellcode:
function farbverlauf1(rot, gruen: Byte): TColor;
begin
  if rot < gruen then
    result := rgb(rot - gruen, 0, 0)
  else
    result := rgb(0, gruen - rot, 0);
end;

function farbverlauf2(rot, gruen: Byte): TColor;
ASM
  cmp al, dl
  jns @kalt
  sub al, dl
  and eax, $0000ff
  ret
  @kalt:
  sub eax, edx
  xor eax, eax // statt   and eax, $00ff00
  mov ah, dl
  //and eax, $00ff00
end;

thomasku 7. Mai 2009 09:22

Re: Rgb mittels Asm darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo himitsu und vielen Dank,

ich habe mir ebenfalls mal die Cpu-Fenster meiner Funktion farbverlauf2 (aus Beitrag6)anzeigen lassen. (Vgl Tasm.jpg)
Das sind einmal die Funktion mit Begin und End und das andere mal ohne.
Meiner Meinung nach legen aber beide Funktionen einen Stackframe an.
Delphi-Quellcode:
Mov ebp,esp //lade Stack pointer in Base pointer
Result erzeugt glaube ebenfalls einen;
Delphi-Quellcode:
Add esp, $0c
jedoch sehe ich nicht die Notwendigkeit
(rechte Seite des Bildes) von:
Delphi-Quellcode:
push ecx //ablegen von ecx auf dem stack
Der Result- STackframe dient doch dann der Sicherung, ist er wirklich unnötig?
Zu mind. solange man noch nicht weiß ob der Code funktioniert.
(Ich habe es nicht nur einmal geschafft Delphi zum abstürzen zu bringen :mrgreen: )


Zur Schnelligkeit, es ist wie gesagt nur ein Bsp an den wir den Umgang mit Asm üben sollen.
Woran erkennt man denn, welches Programm schneller arbeitet, ohne explizit zu testen?
Am Umfang der elementar Operationen?

Habe mir auch schon das Tutorial hierzu durchgelesen:
http://www.delphipraxis.net/internal...ct.php?t=94005

An den negativen Werten arbeite ich noch.

Mfg Thomas


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:10 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