![]() |
Assembler in Delphi! Speichersack?
Ich habe zur Übung ein Stück Quell-Code in Assembler umgewandelt.
Delphi-Quellcode:
Leider gibt es an einer anderen stelle im Programm ein Speicherproblem.
function TColorPalette.HitColorText(apt: TPoint): Integer;
var x : Integer; {begin if PtInRect(ClientRect, apt) then if ((apt.x mod 17) > 14) or ((apt.y mod 17) > 14) then Result := -1 else Result := (apt.x div 17) + (apt.y div 17) * 8 else Result := -1; end;} asm // apt.x div 17 mov eax, apt.x mov ecx, 17 push edx mov edx, 0 div ecx cmp edx, 14 jns @nowhere mov x, eax // apt.y div 17 pop edx mov eax, apt.y mov edx, 0 div ecx cmp edx, 14 jns @nowhere // Result := x + y(eax) * 8 shl eax, 3 or eax, x cmp eax, 40 jns @nowhere mov @Result, eax jmp @1 @nowhere: mov @Result, -1 // Result := -1 @1: end; Wo mach ich was, was ich nicht darf? |
Re: Assembler in Delphi! Speichersack?
Das Ergebnis wird für Integer-Funktionen in EAX zurückgegeben, ansonsten kannst Du natürlich auch Result ansprechen, allerdings ohne die @ Operatoren ;-)
Code:
...:cat:...
function TColorPalette.HitColorText(apt: TPoint): Integer;
var x : Integer; {begin if PtInRect(ClientRect, apt) then if ((apt.x mod 17) > 14) or ((apt.y mod 17) > 14) then Result := -1 else Result := (apt.x div 17) + (apt.y div 17) * 8 else Result := -1; end;} asm // apt.x div 17 mov eax, apt.x mov ecx, 17 push edx mov edx, 0 div ecx cmp edx, 14 jns @nowhere mov x, eax // apt.y div 17 pop edx mov eax, apt.y mov edx, 0 div ecx cmp edx, 14 jns @nowhere // Result := x + y(eax) * 8 shl eax, 3 or eax, x cmp eax, 40 jns @nowhere [color=#ff0000][s] mov @Result, eax[/s][/color] jmp @1 @nowhere: mov [color=#ff001b]EAX[/color], -1 // Result := -1 @1: end; |
Re: Assembler in Delphi! Speichersack?
Liste der Anhänge anzeigen (Anzahl: 1)
Nach Änderung entsteht folgender Fehler...
|
Re: Assembler in Delphi! Speichersack?
Du vergisst den Stack korrekt aufzuräumen.
Delphi-Quellcode:
Zudem verstehe ich nicht warum du
asm
// apt.x div 17 mov eax, apt.x mov ecx, 17 push edx <--- hier EDX auf Stack mov edx, 0 div ecx cmp edx, 14 jns @nowhere <---- hier EXIT ohne EDX vom Stack zu holen mov x, eax // apt.y div 17 pop edx <---- hier EDX vom Stack mov eax, apt.y mov edx, 0 div ecx cmp edx, 14 jns @nowhere // Result := x + y(eax) * 8 shl eax, 3 or eax, x cmp eax, 40 jns @nowhere mov @Result, eax jmp @1 @nowhere: mov @Result, -1 // Result := -1 <----- wenn obiges JNS True ist wird EDX nicht vom Stack geholt @1: end;
Delphi-Quellcode:
in Assembler als
Result := (apt.x div 17) + (apt.y div 17) * 8
Delphi-Quellcode:
codiert hast.
Result := (apt.x div 17) or (apt.y div 17) * 8
Zudem JNS = Jump if not sign, Springe wenn EAX < 0 ! ist falsch
Delphi-Quellcode:
Gruß Hagen
function TColorPalette.HitColorText(apt: TPoint): Integer;
{ var x : Integer; begin if PtInRect(ClientRect, apt) then if ((apt.x mod 17) > 14) or ((apt.y mod 17) > 14) then Result := -1 else Result := (apt.x div 17) + (apt.y div 17) * 8 else Result := -1; end;} asm // in EAX = Self, EDX = @TPoint PUSH EDI MOV ECX,17 MOV EAX,[EDX].TPoint.X MOV EDI,[EDX].TPoint.Y TEST EAX,EAX JS @@Nowhere // P.X < 0 ?? TEST EDI,EDI JS @@Nowhere // P.Y < 0 ?? XOR EDX,EDX DIV ECX CMP EDX,14 JA @@Nowhere // P.X mod 17 > 14 ?? XCHG EAX,EDI // EDI = P.X div 17 XOR EDX,EDX DIV ECX CMP EDX,14 JA @@Nowhere LEA EAX,[EDI + EAX * 8] // Result = P.X div 17 + P.Y div 17 * 8 JMP @@Exit @@Nowhere: XOR EAX,EAX DEC EAX @@Exit POP EDI end; |
Re: Assembler in Delphi! Speichersack?
Delphi-Quellcode:
Ist schon korrekt gewesen wenn ein lokale Stackframe eingerichtet wurde. Der Assembler macht daraus
MOV @Result,-1
Delphi-Quellcode:
Gruß Hagen
MOV EAX,-1
|
Re: Assembler in Delphi! Speichersack?
Übrigens, diese Funktion ist ein ideales Beispiel warum man noch Assembler benutzen sollte.
Denn der Delphi Compiler/Optimierer kann nicht die 4 nötigen Divisionen als 2 Divisionen codieren. Er erkennt deren Abhängigkeiten nicht. Da die Division als solches eine der langsamsten Operationen ist, ist hier ein handgemachter Assembler von Vorteil. Man kann zwar die Division durch 17 beschleunigen, allerdings nützt das hier nicht viel da wir noch den Modulare Rest durch 17 benötigen. Dafür wiederum gibt es keine schnellere Variante als DIV, vorrausgesetzt wir benötigen den modularen Rest UND den Quotienten zu 17. Gruß Hagen |
Re: Assembler in Delphi! Speichersack?
Erstmal danke für die neuen Erkenntnisse!
Delphi-Quellcode:
JA @@Nowhere
Delphi-Quellcode:
Doch diese zwi Zeilen sind mir noch unklar? :gruebel:
LEA EAX,[EDI + EAX * 8] // Result = P.X div 17 + P.Y div 17 * 8
|
Re: Assembler in Delphi! Speichersack?
So ich habe gerade versucht das gegenstück zu verbessern!
Delphi-Quellcode:
Geht das noch eleganter?
function TColorPalette.GetColorRect(aiCol: Integer): TRect;
var x, y : Integer; {begin if aiCol = -1 then Result := Rect(0, 0, 0, 0) else begin x := aiCol mod 8; y := aiCol div 8; Result := Rect(x * 17, y * 17, x * 17 + 14, y * 17 + 14); end; end; } asm push edi test edx, edx js @@nullrect // aiCol < 0 mov edi, 8 mov eax, edx xor edx, edx div edi // aiCol div 8 mov x, edx // = x mov y, eax // = y mov edi, 17 // Abstand // berachne mov eax, x mul edi mov @Result.Left, eax mov eax, y mul edi mov @Result.Top, eax mov eax, x mul edi add eax, 14 mov @Result.Right, eax mov eax, y mul edi add eax, 14 mov @Result.Bottom, eax jmp @@exit @@nullrect: mov @Result.Left, 0 mov @Result.Top, 0 mov @Result.Right, 0 mov @Result.Bottom, 0 @@exit: pop edi end; Warum kann man ecx nicht nutzen |
Re: Assembler in Delphi! Speichersack?
Die division möchte ich nicht dur shr 3 oder and 7 ersetzen da es ja mal 9 oder n spalten werden könnten.
|
Re: Assembler in Delphi! Speichersack?
Delphi-Quellcode:
Gruß Hagen
// EAX = Self, EDX = aCol, ECX = @Result.TRect
asm TEST EDX,EDX JNS @@1 XOR EAX,EAX MOV [ECX].TRect.Left,EAX MOV [ECX].TRect.Right,EAX MOV [ECX].TRect.Top,EAX MOV [ECX].TRect.Bottom,EAX RET @@1: MOV EAX,EDX SHR EDX,3 // aCol div 8 AND EAX,7 // aCol mod 8 LEA EAX,[EAX * 16 + EAX] // X * 16 + X = X * 17 LEA EDX,[EDX * 16 + EDX] // Y * 16 + Y = Y * 17 MOV [ECX].TRect.Left,EAX MOV [ECX].TRect.Top,EDX ADD EAX,14 ADD EDX,14 MOV [ECX].TRect.Right,EAX MOV [ECX].TRect.Borrom,EDX end; { JA = Jump if Above, springe wenn größer, Vorzeichen wird ignoriert JS = Jump if Sign, springe wenn < 0 JNS = Jump not if Sign, springe nicht wenn < 0, bzw. springe wenn >= 0 LEA = Load Effective Address } |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:02 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