Hallo, guten Tag.
Wieder Retro:
Wie muss bitte eine Obj von TurboC++ 3.0 aussehen damit ich sie von PDS
7.1 aufrufen kann und Daten dann mit PDS empfangen kann.
Danke.
Google sagt:
Du musst dich in Basic mit CALL und DECLARE auseinandersetzen.
In c muss die Funktion mit cdecl deklariert werden, und alle Parameter
müssen als call by reference übergeben werden. Das Einbinden wird dann
im Linker gemacht.
https://www.remote.org/frederik/personal/buecher/rammpds.pdf
Wenn du mehr wissen willst musst du schon ein Beispiel zeigen. Bitte
benutze die code tags
Ja , danke für die Info.
Das Buch habe ich mir schon ausgedruckt.
Aber ich finde darin nicht was ich suche und du beschrieben hast.
Mit TASM erzeuge ich schon Obj die wunderbar funktionieren mit Daten
übergabe und Daten rückname in PDS 7.1
1
Aufruf in PDS 7.1 :
2
DECLARE FUNCTION PeekWord%(BYVAL Segment%, BYVAL Address%)
3
DECLARE SUB PokeWord(BYVAL Segment%, BYVAL Address%, BYVAL Value%)
4
5
TASM-Code:
6
7
public PeekWord
8
PeekWord Proc Uses ES, SegAddr:DWord
9
Les BX,SegAddr
10
Mov AX,ES:[BX]
11
Ret
12
PeekWord Endp
13
14
public PokeWord
15
PokeWord Proc Uses ES, SegAddr:DWord, Value:Word
16
Les BX,SegAddr
17
Mov AX,Value
18
Mov ES:[BX],AX
19
Ret
20
PokeWord Endp
Bei C weiss ich es noch nicht.
Funktion mit cdecl und call by reference....?
Peter B. schrieb:> Aber ich finde darin nicht was ich suche und du beschrieben hast.
Seite 294 ist der Syntax von DECLARE beschrieben.
Peter B. schrieb:> Mit TASM erzeuge ich schon Obj die wunderbar funktionieren mit Daten> übergabe und Daten rückname in PDS 7.1
Das funktioniert meiner Meinung nach nur zufällig, da sich Deklaration
in Basic und Asm unterscheiden. Du hast in Basic 2 bzw 3 Parameter in
Asm aber nur 1 bzw 2 params. Das wird nur dann funktionieren wenn du
beim CALL segment und addresse vertauscht übergibst. Intel ist little
endian.
Hier ein c Beispiel (ungetestet) ev sind Tippfehler drin.
1
unsignedint__cdeclPeekWord(unsignedintSeg,Offset)
2
{
3
return*MK_FP(Seg,Offset);
4
}
DECLARE FUNCTION PeekWord% CDECL (BYVAL Segment%, BYVAL Address%)
Wenn du schon gemischte Programmierung betreiben willst musst du dich
wesentlich mehr um Aufrufdetails, Parameterreihenfolge, Stackbereinigung
kümmerten. Das ist in jeder Sprache etwas anders gelöst.
Die PokeWord procedure überlass ich dir als Übung
Thomas Z. schrieb:> Das funktioniert meiner Meinung nach nur zufällig,
Das solltest du wirklich drauf achten Peter - die Regel gilt: Es ist
nicht automatisch richtig oder richtig "genug" wenn es nicht abstürzt
Die Stackkorruption die dabei enstehen erzeugen vielleicht(manchmal)
fehlerhafte Daten und/oder Abstürze
cppbert schrieb:> Thomas Z. schrieb:>> Das funktioniert meiner Meinung nach nur zufällig,>> Das solltest du wirklich drauf achten Peter - die Regel gilt: Es ist> nicht automatisch richtig oder richtig "genug" wenn es nicht abstürzt>> Die Stackkorruption die dabei enstehen erzeugen vielleicht(manchmal)> fehlerhafte Daten und/oder Abstürze
vielleicht(manchmal) = zufällig, kann Stunden, Tage, Wochen nichts
passieren und dann hast du plötzlich ein unerklärliche Programmverhalten
- es ist nicht nur die Call-Stelle die dadurch korrumpiert werden kann
Das ist wie eine Krankheit die man nicht sieht und spürt
Danke für die INfo.
Aber das __cdecl wird in Turbo C++ nicht erkannt.
-------------------------
unsigned int __cdecl PeekWord(unsigned int Seg,Offset)
-------------------------
Im QBX ist nocht der Wurm drin.
BC xquad.bas >>> is ok >>> xquad.obj
TCC squad.c >>> is ok >>> squad.obj
LINK xquad.obj + squad.obj >>> nich ok
(siehe Bild)
Habe hier ein Mini.
Es wird compiliert zur Obj.
Auch damit wird es zur Obj compiliert : cdecl
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <dos.h>
4
#include <conio.h>
5
6
unsigned int _cdecl sqri(int i)
7
{
8
return(i * i);
9
}
Hier das QBX wo das Mecker kommt beim compilat, sieh Bild:
Peter B. schrieb:> unsigned int _cdecl sqri(int i)
wo ist den _cdecl definiert - ich glaube das ist ein Macro
das manchmal auch auf nichts definiert ist - also keine Wirkung
bezüglich
Name-Mangling zeigt d.h. der "_" fehlt dann
geht es auch mit cdecl ohne _ nicht?
unsigned int cdecl sqri(int i)
Thomas Z. schrieb:> Nein er hat einfach einen Fehler in der DECLARE Zeile. Das hat mit> cdecl> nichts zu tun.
in der Doku steht aber das CDECL dafür sorgt das der Unterstrich im
Namen erwartet wird, und in der Turbo C Doku steht das aus - klar kann
er den Namen direkt angeben aber sollte das nicht schon so gehen?
Schau dir nochmal die DECLARE Zeilen an die er hier schon gepostet hat.
Ich hab von Basic ja keine Ahnung aber ob man das %für das
Funktionsergebnis einfach so weglassen kann wage ich Mal zu bezweifeln.
Danke , jetzt funktioniert es.
Wusste nicht , das ihr euch mit solchen alten Sachen noch beschäftigt.
1
QBX-Datei , so muss hier der Name sein : sqri%
2
--------------------------
3
DECLARE function sqri% CDECL (a%)
4
5
x%=100
6
7
y%=sqri%(x%)
8
print y%
9
--------------------------
10
11
C-Datei :
12
--------------------------
13
unsigned int _cdecl sqri(int i)
14
{
15
return(i * i);
16
}
17
--------------------------
Muss dieses CDECL immer mit geschrieben werden bei C und QBX ,
auch wenn ich nur ein C-Prog von QBX aufrufe mit Daten übergabe an C
aber ohne Reückläufer?
Peter B. schrieb:> Muss dieses CDECL immer mit geschrieben werden bei C und QBX ,> auch wenn ich nur ein C-Prog von QBX aufrufe mit Daten übergabe an C> aber ohne Reückläufer?
cdecl definiert die Aufrufkonvention wo der Aufrufer dafür sorgt das der
Stack nach dem Aufruf wieder im richtigen Zustand ist und definiert die
Reihenfolge in der Parameter auf dem Stack landen - Pascal, Basic oder
Watcom C kennen noch x andere Varianten deswegen muss man das klar
definieren
Sonst kommt nur Grütze an - bei einem Parameter kann es noch
funktionieren aber das fehlenden Aufräumen des Stack ist ziemlich
schlecht
Peter B. schrieb:> Muss dieses CDECL immer mit geschrieben werden bei C und QBX ,> auch wenn ich nur ein C-Prog von QBX aufrufe mit Daten übergabe an C> aber ohne Reückläufer?
Vergleichbar mit der Frage ob du auch immer nur im 1. Gang fahren kannst
- kannst du schon, aber dein Motor oder Kupplung fliegen dir dann eben
bald um die Ohren
Das hat mit alten Sachen erst Mal nichts zu tun. cdecl kann man bei c
Programmen auch weglassen weil das der Default ist. Wenn man ein c modul
aber mit fastcall übersetzt ist das cdecl wieder wichtig. Gewöhn es dir
also an die Deklarationen dazuzuschreiben. Es gibt da je nach Compiler
noch vielmehr dieser Deklaratoren.
Auch bei der Windows Programmierung wirst immer wieder darauf stoßen.
Zu Basic kann ich nichts sagen da kenn ich mich nicht aus. Im übrigen
hast du jetzt BYVAL weggelassen warum auch immer. Das sollte für call by
value aber vorhanden sein.
Dein Programm funktioniert übrigens nicht fehlerfrei. Wenn du x%=1000
schreibst wirst du ein lustiges Ergebnis bekommen.
Ja, danke.
Byval habe ich hier vergessen.
-------------------
x%=1000
-------------------
Ja da muss ich dann bei QBX Long einsetzen mit x&=1000 , hat dann 4Byte
und in C muss ich auch Long eintragen. Das x% = Integer.
Peter B. schrieb:> Bei Long funktioniert das nicht???
Dein c code kompiliert nicht?
Dein basic code kompiliert nicht?
Dein programm linkt nicht?
Dein programm liefert nicht das erwartete ergebnis?
Dein programm stuerzt ab?
...
und selbst wenn es funktionieren würde, wäre es immer noch falsch, nur
halt mit größerem Wertebereich. Das c Programm ist nicht die Ursache
deiner Probleme.
Ich kann dir nur empfehlen jetzt endlich mal die Beschreibung von
DECLARE durchzulesen und was noch viel wichtiger ist auch zu verstehen.
Programmieren funktioniert nicht indem man schnell was hinrotzt. Ich
verstehe ehrlich gesagt auch nicht warum du die Hinweise die du ja zu
hauf bekommen hast einfach nicht beachtest.
Thomas Z. schrieb:> Suchttexte im Buch:> BYVAL> LONG> CALL> .....> Lesen und verstehen
Und ganz gut zum lernen ist auch die beiden obj Dateien im IDA
anschauen, das siehst du dann genauer das "Problem" oder wenigstens
erkennen was du noch nicht verstehst
Byval, LONG und CALL ist das wie es im PDS 7.1 Buch steht.
Entweder mit DIM LONG oder so : &
Ich muss Byval nehmen um den Wert zu übergeben und nicht die Adresse.
Und das Call muss ich so gemäß PDS 7.1 nehmen und nicht wie im
Quickbasic.
Bei einer Function wird kein Call genommen.
Ich verstehe die Meldung nicht von QBX.
--------------------------
DECLARE function sqri& CDECL (byval a&)
x&=1000
y&=sqri(x&)
print y&
--------------------------
C-Datei :
--------------------------
long _cdecl sqri(long i)
{
return(1000 * i);
}
--------------------------
Peter B. schrieb:> Ich verstehe die Meldung nicht von QBX.
Früher war nicht alles mit ein gebaut, vielleicht brauchst du fuer long
support noch eine extra lib fuer long support die jetzt beim linken
fehlt
cppbert schrieb:> Peter B. schrieb:>> Ich verstehe die Meldung nicht von QBX.>> Früher war nicht alles mit ein gebaut, vielleicht brauchst du fuer long> support noch eine extra lib fuer long support die jetzt beim linken> fehlt
Nö er muss einfach auch noch gegen die c runtime linken dort ist die
fehlende Funktion dabei. Das macht TC üblicherweise automatisch geht
aber nicht wenn das obj anderweitig verwendet wird.
Thomas Z. schrieb:> cppbert schrieb:>> Peter B. schrieb:>>> Ich verstehe die Meldung nicht von QBX.>>>> Früher war nicht alles mit ein gebaut, vielleicht brauchst du fuer long>> support noch eine extra lib fuer long support die jetzt beim linken>> fehlt>> Nö er muss einfach auch noch gegen die c runtime linken dort ist die> fehlende Funktion dabei. Das macht TC üblicherweise automatisch geht> aber nicht wenn das obj anderweitig verwendet wird.
Völlig richtig
Dann gab es aber auch keine Meldung von QBX sondern vom Linker :)
Die Meldung kam beim linken mit QBX:
Nicht Tlink ......
Sondern mit : LINK testqbx.obj + testtc.obj
Wenn ich nur Integer genommen habe lief das Programm und bei Long kam
wieder die Meldung von QBX
Peter B. schrieb:> Die Meldung kam beim linken mit QBX:>> Nicht Tlink ......>> Sondern mit : LINK testqbx.obj + testtc.obj>> Wenn ich nur Integer genommen habe lief das Programm und bei Long kam> wieder die Meldung von QBX
Weil dein turbo c objekt durch die verwendung von long noch eine lib
zusaetzlich braucht cs.lib oder cm.lib, bis int ist alles mit drin ab
long brauchst du libs
Es hat nichts mit QBX zu tun, probier mal dein Turbo C Programm als Exe
mit main zu bauen dann fügt Turbo C entweder die Lib selbstaendig dazu
oder du bekommst den gleichen Linkerfehler, nur dann eben von TLink
Hm...danke.
Jetzt habe ich es mal mit TCC "squad1.c CM.LIB, CS.LIB" gemacht.
----------------------
long cdecl sqri(long i)
{
return(1000 * i);
}
----------------------
Dann mit :
-----------------------
DECLARE function sqri& CDECL (byval a&)
x&=1000
y&=sqri&(x&)
print y&
-----------------------
BC xquad1.bas
LINK xquad1.obj + squad1.obj
Jetzt kam da die Meldung im Text von QBx vom Fehler aus der Objekt von
squad1.c Ist die C-Datei falsch?
--------------------------
Microsoft (R) BASIC Compiler Version 7.10
Copyright (C) Microsoft Corporation 1982-1990. All rights reserved.
0030 0006 long cdecl sqri(long i)
^ Statement unrecognizable
0030 0006 {
^ Invalid character
0030 0006 return(1000 * i);
^ Syntax error
0030 0006 }
^ Invalid character
---------------------------
Was fischt denn der QBX da heraus?
Deiner linker braucht dein qbx obj, dein turbo c obj und die turbo c
cs.obj (ODER cm.obj), s steht fuer small, m fuer medium
Die fehlermeldungen die du zeigst machen keinen sinn, versuchst du die c
datei mit qbx zu kompilieren?
cppbert schrieb:> Deiner linker braucht dein qbx obj, dein turbo c obj und die turbo> c> cs.obj (ODER cm.obj), s steht fuer small, m fuer medium>> Die fehlermeldungen die du zeigst machen keinen sinn, versuchst du die c> datei mit qbx zu kompilieren?
Baudoch bitte einfach mal ein turboc programm das long verwendet - nicht
immer alles gleichzeitig mit flüchtigkeitsfehler und unklaren
sitationsbeschreibungen
Peter B. schrieb:> So erstelle ich die C-Obj für den QBX:>> TCC squad1.c CM.LIB>> Dann Link von QBX : LINK xquad1.obj + squad1.obj
Das ist ja schön dass du uns zeigst was du machst. Was ist jetzt die
Frage? Warum kannst du eigendlich nicht mal was komplett posten? Wir
sehen von dir immer nur irgendwelche Fragmente.
Die Datei funktioniert in C einwandfrei:
----------------------
long quadrat(long i)
{
return(1000 * i);
}
void main()
{
long lwert,ergebnis;
lwert=1234567;
ergebnis = quadrat(lwert);
}
-----------------------
Habe die dann für QBX genommen :
------------------------
long cdecl quadrat(long i)
{
return(1000 * i);
}
------------------------
Wenn ich die LONG ersetze durch INT für C und QBX funktioniert es.
Ich muss irgendwie in QBX eine LIB reinsetzen.
Aber welche?
Ich gebe auf, jetzt heiß die Funktion auf einmal quadrat. Willst du uns
verarschen?
Nochmal warum zeigst du nicht alles?
Ich sehe bei deiner Post wieder keine Fehlermeldungen....
Woher weißt du überhaupt dass cm.lib die richtige Bibliothek ist?
Damit Namen übersichtlich sind.
Diese habe ich getestet :
CC.LIB , CL.LIB , CM.LIB , CS.LIB , CH.LIB
Die selbe Fehlermeldung wie hier oben : 10.04.2020 15:34
Peter B. schrieb:> Damit Namen übersichtlich sind.>> Diese habe ich getestet :> CC.LIB , CL.LIB , CM.LIB , CS.LIB , CH.LIB
C compact
L large
M medium
S small
H huge
Warum probierst du alle durch? Welches Speichermodel benutzt du bei
Turbo c? Oder was ist da default?
> Die selbe Fehlermeldung wie hier oben : 10.04.2020 15:3
Dir traut da keiner so recht weil du zwischen durch x kleine aenderungen
machst, du von qbx sprichst aber den linker meinst, dann c code mit qbx
kompilieren willst usw.
Dein probieren + häppchen infos erzeugen ein unklares bild wie
strukturiert du vorgehst
Btw: welche libs, obj werden denn bei deinem turbo c main programm
verlinkt? Kannst du auch mit IDA sehen wenn du deine turbo c main obj
anschaust - nicht die exe
Ich muss noch einmal schauen was das QBX so macht mit dem OBJ vom TCC.
Für mich ist das Verdächtige das QBX.
-------------------------------
/AH Ermöglicht "Huge Arrays" (siehe Kapitel 12.4). Alle EXEProgramme,
die aus QBX heraus erstellt werden, werden ebenfalls mit /AH kompiliert,
wenn dieser Switch angegeben wird.
-------------------------------
Darum nehme ich für das TCC dieses CH.LIB
Peter B. schrieb:> Ich muss noch einmal schauen was das QBX so macht mit dem OBJ vom> TCC.> Für mich ist das Verdächtige das QBX.>> -------------------------------> /AH Ermöglicht "Huge Arrays" (siehe Kapitel 12.4). Alle EXEProgramme,> die aus QBX heraus erstellt werden, werden ebenfalls mit /AH kompiliert,> wenn dieser Switch angegeben wird.> ------------------------------->> Darum nehme ich für das TCC dieses CH.LIBPeter B. schrieb:> Ich muss noch einmal schauen was das QBX so macht mit dem OBJ vom> TCC.> Für mich ist das Verdächtige das QBX.>> -------------------------------> /AH Ermöglicht "Huge Arrays" (siehe Kapitel 12.4). Alle EXEProgramme,> die aus QBX heraus erstellt werden, werden ebenfalls mit /AH kompiliert,> wenn dieser Switch angegeben wird.> ------------------------------->> Darum nehme ich für das TCC dieses CH.LIB
Gibst du den /AH switch an? Sonst ist die Info einfach unrelevant
TCC /? > cmd.txt
Leitet die Ausgabe in die Text datei cmd.txt, damit keine Screenshots
posten musst
Die QBX Kommandozeilenoption bekommt man bestimmt auch mit QBX /?
Und von LINK.EXE auch
"bc /AH xsquad1.bas" gebe ich an.
"tcc -mh squad1.c CH.LIB" gehe ich an.
Es kommt bei allem immer diese Meldung außer bei Integer wenn ich mit
QBX compiliere : LINK xsquad1.obj + squad1.obj
Würde jetzt nach Zeigern tendieren.
--------------------------
long cdecl quadrat(long i)
{
return(1000 * i);
}
--------------------------
Wie geht das hier bitte mit Segment und Offset übergabe bei C?
Ich kann ja das Segment und die Offset von der Variablen in QBX
übergeben.
Danke.
Lass das mit Huge(das fieseste und fetteste von allen Speichermodellen),
das hat doch gar keine relevanz fuer dich, fuer dich reicht Small(ist
auch der Standard bei den meisten Programmen) bitte nicht zur Lösung
hingurken indem du alle Optionen mal durch probierst
>QBX compiliere : LINK xsquad1.obj + squad1.obj
du sprichst von kompilieren und zeigst den linkeraufruf? Dir ist der
unterschied klar?
Nur so als Tip: wenn der Linker was fehlendes meldet fehlt dem Linker
eine obj oder lib, es kann aber sein das du dann den tlink benutzen
musst - bin mir nicht sicher ob das lib format was turbo c proprietäres
ist
QBX,bc,tcc,linker?
Bc.exe ist dein basic kompiler der aus basic source obj erzeugt (oder
auch direkt eine exe mit Einbindung des linkers), interessiert sich
nicht fuer libs oder objs, er erzeugt sie
Tcc.exe ist dein Turbo C Kompiler der aus c source obj erzeugt (oder
auch direkt exe unter Einbindung des Linkers), interessiert sich nicht
fuer libs oder objs, er erzeugt sie
Link.exe ist der Microsoft linker der obj oder libs zu exen
zusammenbindet
Was ist jetzt in diesem spiel hier QBX mit dem du scheinbar auch noch
kompilierst? oder ist das der bc den du hin und wieder mal anders nennst
Peter B. schrieb:> Hmmm...> Natürlich führe ich die beiden Obj zusammen zu einer EXE.>> Das Basicprogramm bildet die Haupt OBj und TCC bildet die dazugehörige> Obj von C.
Und wie bringt der linker den cs.lib code in die exe, dem ursprung der
LXMUL?
cppbert schrieb:> Peter B. schrieb:>> Hmmm...>> Natürlich führe ich die beiden Obj zusammen zu einer EXE.>>>> Das Basicprogramm bildet die Haupt OBj und TCC bildet die dazugehörige>> Obj von C.>> Und wie bringt der linker den cs.lib code in die exe, dem ursprung der> LXMUL?
Tip: dein tcc steckt den code von cs.lib nicht zur kompilierzeit mit in
deine tc obj datei (die angabe beim tcc ist sinnfrei), der Linker
erwartet den code zur linkzeit
Also das kann man ja nicht mehr mit ansehen. Ich hab mir jetzt mal das
Basic runtergeladen und das mal kurz ausprobiert. Das Basic Programm
habe ich wie im Buch empfohlen mit DIM ergänzt. Im c Programm muss die
Funktion als far dedeklariert werden sonst stürzt die exe ab.
Dann noch schnell eine build.bat und ein linker.cmd geschrieben und o.
Wunder es funktioniert.
Build.bat:
1
BC test test test
2
tcc -c sqri.c
3
link @linker.cmd
linker.cmd:
1
test.obj +
2
sqri.obj
3
test.exe
4
test.lst
5
cs.lib +
6
brt71enr.lib
Hinweis ev müssen Pfadangaben angepasst werden ich hab das bewusst
weggelassen.
Au...weia.....
Danke, ein schönes Ostergeschenk.
Wo ergänzt bitte?
----------------------
DIM ergänzt.
----------------------
Bei mir funktioniert es ohne.
Danke.
Note that "ENR" in BRT71ENR.LIB refers to "E" for IEEE math, "N" for
near strings, and "R" for MS-DOS (real) mode.
BRT71ENR.LIB steht fuer (B)asic (R)un(t)ime 7.1 ENR = E: IEEE Mathe, N:
Near Strings, R: MSDOS real mode
>Im c Programm muss die>Funktion als far dedeklariert>werden sonst stürzt die exe ab.
Das ist aber nicht immer noetig, oder? Oder entspricht ein obj mind.
einem segment und es darf da keinen merge oder sowas geben d.h. far ist
pflicht
cppbert schrieb:>> Im c Programm muss die >Funktion als far dedeklariert>> werden sonst stürzt die exe ab.>> Das ist aber nicht immer noetig, oder? Oder entspricht ein obj mind.> einem segment und es darf da keinen merge oder sowas geben d.h. far
Keine Ahnung dafür weiß ich zu wenig über Basic und im speziellen über
qbx.
Es ist aber auch so im Buch beschrieben, weshalb ich mir die Frage
stelle wie es jemals beim TO funktioniert hat.
Bei mir ist jedenfalls die exe abgestürzt wenn ich far weggelassen habe.
Peter B. schrieb:> Warum müssen bitte die beiden drin sein:>> ------------------------> xsquad1.exe> xsquad1.lst> ------------------------
müssen sie nicht. Das Format und die Einträge sind im Buch sehr gut
erklärt.
In Zukunft waeres schön wenn du Thomas Beispiel folgst und immer deinen
ganzen Quelltext nebst einer passenden Build.bat hier als Anhang mit
allen Fehlern veroeffentlichst, dann musst du weniger erklären und alle
Infos sind eindeutig
1
Build.bat > out.txt 2>&1
Das 2>&1 leitet stderr auf stdout, also kommen dann auch die Fehler in
die Datei
Ich rufe fuer solche Test dosbox per Batchdatei auf damit das Build.bat
gleich in dosbox läuft und danach dosbox wieder beendet
Danke für die Info.
Meine DosBox-X rufe ich auch so auf,bzw über ein Startbutton mit
Purebasic.
---------------------------
Bei mir ist jedenfalls die exe abgestürzt wenn ich far weggelassen habe.
---------------------------
Es funktionierte bei mir wenn ich Integer verwendet habe und keine LONG.