Pascal String to PChar

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Antworten
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Pascal String to PChar

Beitrag von Dosenware »

Gruß,

hat wer eine Idee wo der Unterschied zwischen den Nullterminierten Strings ist, den beide Codeschnipsel ({1} / {2}) zurueckliefern?

Beide liefern einen String zurueck, der sich in Pascal scheinbar voellig normal verhaelt (also write klappt), aber nur der von Code {1} zurueckgelieferte String laesst sich in Interruptroutienen (int 21h) verwenden...

Das Ergebnis von StrPCopy funktioniert bei dem Interrupt uebrigens auch nicht...

Borland Pascal 7

Code: Alles auswählen

   function StrToPChar(Name:String):Pchar;
    type CharArray=array[0..255]of Char;
    var  StrHelper:CharArray absolute Name;
         PChHelper1:PChar;
         PChHelper2:^CharArray absolute PChHelper1;
         i:word;
    begin
{1}
    PChHelper1:=#0      ...::EDIT: gekuerzt, #0 stand hier 256 mal::...
    for i:=0 to ord(StrHelper[0])-1 do
     PChHelper2^[i]:=StrHelper[i+1];
    PChHelper2^[ord(StrHelper[0])]:=#0; {EDIT: Pflaster, da irgendwie lange Strings Reste hinterlassen}
{/1}
    StrToPChar:=PChHelper1;
    end;

{2}	
	for i:=0 to ord(StrHelper[0])-1 do
     PChHelper2^[i]:=StrHelper[i+1];
    PChHelper2^[ord(StrHelper[0])]:=#0;
{/2}
Zuletzt geändert von Dosenware am Di 4. Mär 2008, 13:36, insgesamt 1-mal geändert.
elianda
DOS-Übermensch
Beiträge: 1150
Registriert: Mi 31. Jan 2007, 19:04
Wohnort: Halle
Kontaktdaten:

Beitrag von elianda »

Ich bin mir nicht ganz sicher, da du hier null terminierte Strings verwendest.
Die klassischen DOS Funktionen zur Ausgabe erwarten aber $ terminierte Strings.

z.B.:
http://www.fh-wedel.de/~bek/asm/int21.html#int2109

Edit: Ok nicht alle verwenden $ als Ende Zeichen, aber die zur Ausgabe eben.
Ansonsten pruefe einfach mal, ob vor dem INT Aufruf (Breakpoint) wirklich alle Register auf den korrekten Werten stehen und wie der String im Speicher aussieht.
Ein klassischer Fehler ist imho auch, dass man vergisst DS wieder zu rekonstruieren.
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Beitrag von Dosenware »

mit der {1} Variante gehts ja, also sollten die Register richtig gesetzt sein
Die Register sollte Pascal eigentlich selber rekonstruieren, der Interruptaufruf ist ein eigenes UP.

Int ist 21h; AX=714E (und was dazugehoert)

weiteres Problem gefunden: bei {1} scheinen mehrfachaufrufe Spuren zu hinterlassen, wenn auf einen langen String ein kurzer folgt, haengen hinten die Reste vom langen String dran...

Edit: hab da jetzt mal ein "PChHelper2^[ord(StrHelper[0])]:=#0;" Pflaster an {1} rangehaengt

Das sollte doch eigentlich durch die 256 mal #0 ueberschrieben werden...?... (PChHelper1)

Entweder ist da was kaputt, oder der Compiler optimiert das weg...was aufs gleiche hinauslaeuft...
elianda
DOS-Übermensch
Beiträge: 1150
Registriert: Mi 31. Jan 2007, 19:04
Wohnort: Halle
Kontaktdaten:

Beitrag von elianda »

Hmm also ich habe da snicht probiert und das ist nur eine Vermutung:
Ist PChar nicht ein Pointer auf Char, also muesste doch da stehen:

PChHelper1^:=#0...;
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Beitrag von Dosenware »

nein das passt schon so, macht Pascal automatisch, deine Variante gibt nur eine Fehlermeldung des Compilers.

den Zeiger muss ich nur bei PChHelper2 beachten (absolute PCHelper1)

edit1: wegeditiert

Edit2: jetzt hab ichs, vorher hatte ich immer den Speicher verwuestet, in Methode {1} hatte ich einen Definierten Speicherbereich fuer den Typecast

hier die optimierte, fertige Version - ich glaube viel kuerzer geht der TypeCast nicht...

Code: Alles auswählen

   function StrToPChar(Name:String):Pchar;
    var  StrHelper:array[0..255]of Char absolute Name;
         PChHelper:PChar;
    begin
    PchHelper:=@Name;
    inc(PChHelper); {ueberspringen des Laengenbytes}
    StrHelper[ord(StrHelper[0])+1]:=#0;
    StrToPChar:=PChHelper;
    end;
EDIT3:
Jetzt extra nochmal aufgestanden um es aufzuschreiben...

Code: Alles auswählen

   function StrToPChar(Name:String):Pchar;
    var PChHelper:PChar;
    begin
    Name:=Name+#0;
    PchHelper:=@Name;
    inc(PChHelper);
    StrToPChar:=PChHelper;
    end;
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Beitrag von Dosenware »

Gruß,

Neue Frage: weiß jemand, wie bei BP7 ein File im Speicher aussieht?
Ich wuerde gern das assign durch eine Variante mit unterstuetzung langer Dateinamen ersetzen...

/Gruß

EDIT:
hmm, folgende Variante muesste moeglich sein (ist zwar nur ein Pflaster - aber zur Not tuts das auch):

Int 21/AX=716Ch (Create or open file DX:=9 == oeffnen, oder erzeugen) - damit es die Datei fuer die naechsten Schritte wirklich gibt...
Int 21/AH=3Eh (close file)
Int 21/AX=7160h/CL=01h (getshortname)
assign(file,Shortname)

Int 21/AX=71A8h (Generate Short filename) scheidet aus, da er etwas anders arbeitet als das Dateisystem, d.h. eine evtl. bereits vorhandene Datei koennte "uebersehen" werden

Edit: mal so nebenbei: Overload ist unter BP7 nicht drin, oder?
(Overload: Das definieren mehrer gleichnamiger unterprogramme, nuetzlich wenn man es mit wechselnden Parametertypen zu tun hat - oder einfach nur "optionale" Parameter haben will)
Antworten