Entwickler-Ecke
Algorithmen, Optimierung und Assembler - [Assembler] Problem bei mehrfachem MOV
Silas - Mo 12.05.08 19:08
Titel: [Assembler] Problem bei mehrfachem MOV
Hallo!
Ich hab mal wieder ein (eigenartiges) Problem.
Mein Code funktionierte bis vor Kurzem einwandfrei, aber jetzt spielt er verrückt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure Bin2Hex(Source: Pointer; Length: Cardinal; Dest: PChar; Uppercase: Boolean); assembler; procedure Bin2Hex(Source: Pointer; Length: Cardinal; Dest: PChar; Uppercase: Boolean); asm push ebx mov bl, 10h mov esi, Source mov ecx, Length mov edi, Dest mov al, UpperCase test al, al jz @lc pop ebx end; |
Der Code an sich dürfte klar sein; Source, Length und Dest werden in ihre Register geschrieben.
Da liegt jetzt das Problem: Sowohl ecx als auch edi erhalten den Wert von Length. Wenn ich das Ganze umdrehe, erhalten beide den Wert von Dest. :nut: (Ja, sie haben den Wert nachher wirklich, das liegt nicht am Debugger. Die Werte stehen zumindest in der AV :? )
Wenn ich statt diesem den auskommentierten Code verwende, funktioniert alles einwandfrei.
Was ist da los? :?!?: Hat das evtl. etwas mit der
assembler-Direktive oder der Parameterübergabe zu tun (kein
const /
var)? Sollte man bei reinen Assemblerfunktionen eine andere Aufrufkonvention verwenden?
BenBE - Mo 12.05.08 19:45
Die Angabe Assembler wird von Delphi ignoriert, da sie nicht nötig ist.
Zu deinem Problem: Nur EAX, EDX und ECX sind frei verfügbar. Jegliche andren Register (EBX, EDI, ESI) müssen gesichert und wiederhergestellt werden.
Silas - Mo 12.05.08 20:27
BenBE hat folgendes geschrieben: |
Die Angabe Assembler wird von Delphi ignoriert, da sie nicht nötig ist. |
Oh, hätte gedacht sie wäre nötig, wenn die Prozedur keinen
begin-
end-Block hat. Man lernt nie aus ;) .
BenBE hat folgendes geschrieben: |
Zu deinem Problem: Nur EAX, EDX und ECX sind frei verfügbar. Jegliche andren Register (EBX, EDI, ESI) müssen gesichert und wiederhergestellt werden. |
Bei EBX wusste ich das, die Indexregister haben mir bis jetzt nie Probleme bereitet. Das Sichern ändert auch nichts am Problem (das ja (auch laut Debugger) bei der Zuweisung besteht). :nixweiss:
BenBE - Mo 12.05.08 20:44
ESI und EDI werden für OOP bei Delphi genutzt (glaub ESI war der Self-Pointer, EDI die Klassen-Referenz). Wenn Du die also in deiner Routine änderst, ...
Ferner solltest Du beachten, was Du in den ersten Zeilen geschrieben hast (Vergleich mal mit dem CPU-Fenster :P):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure Bin2Hex(Source: Pointer; Length: Cardinal; Dest: PChar; Uppercase: Boolean); assembler; procedure Bin2Hex(Source: Pointer; Length: Cardinal; Dest: PChar; Uppercase: Boolean); asm push ebx mov bl, 10h mov esi, EAX mov ecx, EDX mov edi, ECX mov al, BYTE PTR [ESP+4] test al, al jz @lc pop ebx end; |
Merk Dir am Besten die Zuordnung der Register für die Register-Aufruf-Konvention und arbeite damit. Ist IMMER EAX, EDX, ECX und der Rest Stack, zugeordnet von Links nach Rechts.
Silas - Mo 12.05.08 21:11
BenBE hat folgendes geschrieben: |
ESI und EDI werden für OOP bei Delphi genutzt (glaub ESI war der Self-Pointer, EDI die Klassen-Referenz). Wenn Du die also in deiner Routine änderst, ... |
Gut, meine Funktionen sind global, insofern ist es in dem Fall egal. Werds mir aber merken, danke für den Tip ;) .
BenBE hat folgendes geschrieben: |
Ferner solltest Du beachten, was Du in den ersten Zeilen geschrieben hast (Vergleich mal mit dem CPU-Fenster :P):
...
Merk Dir am Besten die Zuordnung der Register für die Register-Aufruf-Konvention und arbeite damit. Ist IMMER EAX, EDX, ECX und der Rest Stack, zugeordnet von Links nach Rechts. |
:shock: Oha. Wusste nicht, dass Delphi ohne explizite
register-Direktive die Register an Stelle des Stacks verwendet. Man gewöhnt sich so schnell an MASM... :D
Beim rumprobieren ist mir aufgefallen, dass sich das Problem mit
stdcall lösen lässt, ich wusste nur nicht warum. Dann dreh ich die Zuweisungen mal ein wenig um :) .
Danke für die Hilfe!
BenBE - Mo 12.05.08 21:22
Silas hat folgendes geschrieben: |
BenBE hat folgendes geschrieben: | ESI und EDI werden für OOP bei Delphi genutzt (glaub ESI war der Self-Pointer, EDI die Klassen-Referenz). Wenn Du die also in deiner Routine änderst, ... | Gut, meine Funktionen sind global, insofern ist es in dem Fall egal. Werds mir aber merken, danke für den Tip ;) .
BenBE hat folgendes geschrieben: | Ferner solltest Du beachten, was Du in den ersten Zeilen geschrieben hast (Vergleich mal mit dem CPU-Fenster :P):
...
Merk Dir am Besten die Zuordnung der Register für die Register-Aufruf-Konvention und arbeite damit. Ist IMMER EAX, EDX, ECX und der Rest Stack, zugeordnet von Links nach Rechts. | :shock: Oha. Wusste nicht, dass Delphi ohne explizite register-Direktive die Register an Stelle des Stacks verwendet. Man gewöhnt sich so schnell an MASM... :D
Beim rumprobieren ist mir aufgefallen, dass sich das Problem mit stdcall lösen lässt, ich wusste nur nicht warum. Dann dreh ich die Zuweisungen mal ein wenig um :) .
Danke für die Hilfe! |
Bei STDCall funkzt es, weil stdcall für alles den Stack (von Rechts nach Links) nutzt ...
Silas - Mo 12.05.08 21:38
BenBE hat folgendes geschrieben: |
Bei STDCall funkzt es, weil stdcall für alles den Stack (von Rechts nach Links) nutzt ... |
Weiß ich, ich hatte mich nur darüber gewundert, weil ich davon ausgegangen bin, dass das Problem - nachdem es ja mit stdcall funzt - damit zusammenhängt, dass die Pascal-Konvention "falschherum" arbeitet. ;)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!