![]() |
Rgb mittels Asm darstellen
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
Ich möchte gern die rgb Funktion mittels assemblercode darstellen.
Delphi-Quellcode:
MIt dieser bekomme ich zwar ein ähnliches Ergebnis, allerdings dunkler(wobei beides integer, a 8 Bit sind).
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; Siehe dazu Bild. Folgende Funktion hatte ich ursprünglich, hier erhalte ich aber nur einen teil.
Delphi-Quellcode:
Mfg thomas
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; |
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.) |
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 |
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. |
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:
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... ;-)
sub edx,eax;
Mov result,Eax; 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. |
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:
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:
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; 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 |
Re: Rgb mittels Asm darstellen
Schreib das einfach so:
Delphi-Quellcode:
Die Parameter liegen der Reihe nach in EAX, EDX und ECX, danach auf dem Stack. Das Ergebnis gehört in EAX.
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; (Ausnahme wäre ein String als Rückgabewert. Dabei wird der String für das Ergebnis wie ein weiterer Parameter übergeben.) |
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 |
Re: Rgb mittels Asm darstellen
Liste der Anhänge anzeigen (Anzahl: 1)
Delphi-Quellcode:
erstmal das Begin-End ... darum wird doch bestimmt ein "unnötiger" Stackframe erstellt
function farbverlauf2(rot,gruen:integer):TColor;
begin ASM @kalt: sub edx,eax; 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:
unten im Bild:
function farbverlauf2(rot, gruen: Integer): TColor;
begin if rot < gruen then result := rot - gruen else result := (gruen - rot) shl 8; end;
Code:
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:
[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]
Delphi-Quellcode:
[edit]
function farbverlauf2(rot, gruen: Integer): TColor; Inline;
begin if rot < gruen then result := rot - gruen else result := (gruen - rot) shl 8; end; 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; |
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:
Result erzeugt glaube ebenfalls einen;
Mov ebp,esp //lade Stack pointer in Base pointer
Delphi-Quellcode:
jedoch sehe ich nicht die Notwendigkeit
Add esp, $0c
(rechte Seite des Bildes) von:
Delphi-Quellcode:
Der Result- STackframe dient doch dann der Sicherung, ist er wirklich unnötig?
push ecx //ablegen von ecx auf dem stack
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: ![]() An den negativen Werten arbeite ich noch. Mfg Thomas |
Re: Rgb mittels Asm darstellen
Das PUSH ECX gehört zum Standardverhallten des Compilers.
Der automatisch erzeugte Eintritts- und Austrittscode:
Delphi-Quellcode:
Standardmäßig sind, laut Intel-Sepzifikation, EAX, EDX und ECX, sowie die Statusregister frei verfügbar
PUSH EBP // Vorhanden wenn Locals <> 0 oder Params <> 0
MOV EBP, ESP // Vorhanden wenn Locals <> 0 oder Params <> 0 SUB ESP, Locals // Vorhanden wenn Locals <> 0 PUSH ECX // - ... MOV EAX, [EBP-4] // Vorhanden wenn nachdem &Result etwas zugewiesen wurde auch noch EAX etwas zugewiesen // wird, in diesem Fall wird für &Result [EBP-4] statt EAX verwendet - wenn Result <= Integer POP ECX // - MOV ESP, EBP // Vorhanden wenn Locals <> 0 POP EBP // Vorhanden wenn Locals <> 0 oder Params <> 0 RET Params // Immer vorhanden und alle anderen Register müssen nach der Prozedur/Funktion wieder hergestellt werden. Allerdings verwendet Delphi das ECX intern für eigene Dinge, weßhalb es dieses sicherheitshalber selber nochmal sichert, da der Programmierer es (laut Spec) ja nicht selber machen muß. |
Re: Rgb mittels Asm darstellen
Mal was Grundsätzliches zum Farbverlauf.
Ein "g'scheite" Funktion zum Berechnen eines Farbverlaufs braucht 3 Parameter: * Anfangsfarbe * Endfarbe * Überblendungsfaktor Der Überblendungsfaktor könnte ein Double im Bereich 0.0 bis 1.0 oder auch 0% bis 100% sein. Wenn man Integerarithmetik einsetzen möchte (gerade auch weil man die Funktion in Assembler implementieren will) dann kann man den Überblendungsfaktor auch von 0 bis 255 (Datentyp Integer) festlegen. Ich verweise hier mal auf ![]() Du kannst versuchen die Funktion ColorBetween() in Assembler umzusetzen. Den Aufruf von ColorToRGB() kann man sich schenken, wenn man sicherstellt, dass keine Systemfarben wie z.B. clWindow übergeben werden. Den Aufruf von GetRValue(), GetGValue() und GetBValue() braucht man auch nicht, wenn man die Farbkomponenten rot, grün und blau direkt aus TColor rausholt. |
Re: Rgb mittels Asm darstellen
Hallo himitsu und vielen Dank!
Hallo shmia, habe mich mal daran probiert, scheint aber noch zu schwierig! Danke aber dafür, ist recht interessant. Warum darf man keine Systemfarben übergeben bzw warum stören die 2 Nullen? 00XXXXXXX mal mein bisheriges Ergebnis :oops: (immerhin werden es schon 2 unterschiedlich gefärbte Vierecke :mrgreen: )
Delphi-Quellcode:
Mfg Thomas
function ColorBetween2(a,b:TColor;c:integer):TColor;
ASM // Shl eax,24; //cmp al,$00; // cmp ah,$00; // je @weiter; Sub dl,al; Xchg al,dl; Mul dl; add al,dl; Sub dx,ax; Xchg ax,dx; Mul dx; add ax,cx; shl ax,8; Sub edx,eax; Xchg eax,edx; Mul edx; add eax,ecx; shl eax,16; Ret; //@weiter:; END; //Edit also 2 unterschiedliche Vierecke wenn man die Kommentarklammeren entfernt |
Re: Rgb mittels Asm darstellen
die zwei 00 stören nicht, aber Farben aus gewissen paletten
Delphi-Quellcode:
so hat z.B. clBackground den Wert $FF000001 (auch so zu finden in der Unit Graphics von Delphi)
// Quelle siehe Anhang
Const COLOR_SCROLLBAR = TColorIndex(0); COLOR_BACKGROUND = TColorIndex(1); COLOR_ACTIVECAPTION = TColorIndex(2); cpSystemPalette = $00; cpActingPalette = $01; cpLogicalPalette = $02; cpNoColor = $1F; cpDefaultColor = $20; cpSystemColor = $FF; clScrollBar = TColor(cpSystemColor shl 24 or COLOR_SCROLLBAR); clBackground = TColor(cpSystemColor shl 24 or COLOR_BACKGROUND); clActiveCaption = TColor(cpSystemColor shl 24 or COLOR_ACTIVECAPTION); Function ColorToRGB(Color: TColor): TColor; Var _Color: TColorRec Absolute Color; Begin If _Color.Palette = cpSystemColor Then Result := GetSysColor(Color and $FF) and $FFFFFF Else If _Color.Palette in [cpSystemPalette..cpLogicalPalette] Then Result := Color and $FFFFFF Else Result := $000000; End; Speziell die Systemfarben sind über ihren Index kodiert und müssen erst entschlüsselt werden. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:25 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