Autor Beitrag
Silas
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 478

Windows XP Home
Delphi 2005, RAD Studio 2007, MASM32, FASM, SharpDevelop 3.0
BeitragVerfasst: Mo 12.05.08 19:08 
Hallo!

Ich hab mal wieder ein (eigenartiges) Problem.
Mein Code funktionierte bis vor Kurzem einwandfrei, aber jetzt spielt er verrückt:
ausblenden 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       // bl = Divisor (16)
        mov esi, Source   // esi = Quelladresse
        mov ecx, Length   // ecx = Verbleibende bytes
        mov edi, Dest     // edi = Zieladresse       
        {push Source
        push Length
        push Dest
        pop edi
        pop ecx
        pop esi}

        mov al, UpperCase
        test al, al       // Großbuchstaben?
        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?

_________________
Religionskriege sind nur Streitigkeiten darüber, wer den cooleren imaginären Freund hat ;-)
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Silas Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 478

Windows XP Home
Delphi 2005, RAD Studio 2007, MASM32, FASM, SharpDevelop 3.0
BeitragVerfasst: Mo 12.05.08 20:27 
user profile iconBenBE 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 ;) .

user profile iconBenBE 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:

_________________
Religionskriege sind nur Streitigkeiten darüber, wer den cooleren imaginären Freund hat ;-)
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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):

ausblenden 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       // bl = Divisor (16)
        mov esi, EAX      // esi = Quelladresse
        mov ecx, EDX      // ecx = Verbleibende bytes
        mov edi, ECX      // edi = Zieladresse       
        {push Source
        push Length
        push Dest
        pop edi
        pop ecx
        pop esi}

        mov al, BYTE PTR [ESP+4]
        test al, al       // Großbuchstaben?
        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.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Silas Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 478

Windows XP Home
Delphi 2005, RAD Studio 2007, MASM32, FASM, SharpDevelop 3.0
BeitragVerfasst: Mo 12.05.08 21:11 
user profile iconBenBE 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 ;) .

user profile iconBenBE 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!

_________________
Religionskriege sind nur Streitigkeiten darüber, wer den cooleren imaginären Freund hat ;-)
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 12.05.08 21:22 
user profile iconSilas hat folgendes geschrieben:
user profile iconBenBE 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 ;) .

user profile iconBenBE 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 ...

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Silas Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 478

Windows XP Home
Delphi 2005, RAD Studio 2007, MASM32, FASM, SharpDevelop 3.0
BeitragVerfasst: Mo 12.05.08 21:38 
user profile iconBenBE 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. ;)

_________________
Religionskriege sind nur Streitigkeiten darüber, wer den cooleren imaginären Freund hat ;-)