Entwickler-Ecke

Windows API - Assembler


.Johannes. - Mo 05.01.04 14:50
Titel: Assembler
Hi!
Ich habe folgende Funktion eingebaut:

Delphi-Quelltext
1:
2:
3:
4:
5:
function MessageBox (
    HWnd: Integer; 
    Text, Caption: 
    PChar; Flags: Integer
  ): Integer; stdcallexternal 'user32.dll' name 'MessageBoxA';


Nun habe ich zwei Strings: Text und Titel.
Jetzt kann ich mit "Messagebox (0,Text,Titel,0);" die Message anzeigen.
wenn ich es aber in Assembler versuche mit:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
asm 
push 0 
push offset Text 
push offset Titel 
push 0 
call Messagebox 
end;


dann fliege ich aus dem Programm raus, mit dem Hinweis auf irgendeine Zugriffsverletzung.

Moderiert von user profile iconMotzi: Delphi-Tags hinzugefügt


Anonymous - Mo 05.01.04 15:03

Probier es mal so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
var
 a,b: string;
begin
 a := 'foo';
 b := 'bar';
 asm
  push 0
  lea eax,a
  call UniqueString
  push eax
  lea eax,b
  call UniqueString
  push eax
  push 0
  call MessageBox
 end;
end;


Motzi - Mo 05.01.04 18:33

Ein Auruf von UniqueString ist an dieser Stelle unnötig..! Man muss halt bei dem ganzen bedenken, dass Delphi-Strings (zumindest die Ansi-Strings) eigentlich auch nur Pointer sind...


Anonymous - Mo 05.01.04 19:38

Eben nicht. Nach dem Aufruf von Uniquestring befindet sich in eax die Speicheradresse des ersten Buchstabens in a/b. (=> entspricht PChar)
Die Speicheradresse der Variablen entspricht aber nicht PChar, wodurch es zu einer AE kommt.


Motzi - So 11.01.04 23:06

obbschtkuche hat folgendes geschrieben:
Eben nicht. Nach dem Aufruf von Uniquestring befindet sich in eax die Speicheradresse des ersten Buchstabens in a/b. (=> entspricht PChar)
Die Speicheradresse der Variablen entspricht aber nicht PChar, wodurch es zu einer AE kommt.

Oops.. hab den Thread damals ganze vergessen.. das kommt davon wenn man nicht auf seine Emails zugreifen kann.. :?

UniqueString sorgt dafür, dass der String in einen neuen Speicherbereich kopiert wird und der Referenzzähler auf 1 gesetzt wird. Das ist bei APIs notwendig die Daten im übergeben String ablegen, denn wenn mehrere Strings dieselbe Zeichenkette referenzieren (Referenzzäher > 1), dann werden alle diese Strings von einer Änderung beeinflusst!

Probier mal folgenden Aufruf:

Delphi-Quelltext
1:
2:
3:
4:
5:
var
  s: String;

s := 'Test';
MessageBox(Pointer(s), Pointer(s), 0);

und schau mal was der Compiler daraus macht... was für eine Überraschung, er pusht nur die Adresse auf die der String s zeigt, denn ein Delphi-String ist bereits ein Zeiger auf eine Zeichenkette, so wie ein PChar! ;)

Ich bin gerade dabei ein Tutorial über Strings, die String-Internals und alles möglicher rundherum zu schreiben... da steht das auch in allen Details drinnen beschrieben...!


Anonymous - Mo 12.01.04 17:03

oh, interessant... da wundert mich aber, was der compiler aus


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
 s: String;
begin
 s := 'Test';
 MessageBox(0, pchar(s), pchar(s), 0);
end;


macht. Und da erstaunt mich auch der Unterschied zwischen @s und @s[1]. Eigentlich ist @s[1] dann ja der pchar...


Motzi - Mo 12.01.04 20:27

Ja... es gibt 3 Möglichkeiten auf PChar zu casten:

PChar(String)
@String[1]
Pointer(String)

und jede dieser Möglichkeiten wird vom Compiler anders umgesetzt... aber die Details dazu stehen alle in meinem Tutorial, welches ich hoffentlich eh in Kürze veröffentlichen kann...