Problem mit Lib

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • Problem mit Lib

    Hallo Zusammen

    Ich habe ein Problem mit den $External Befehl, der in der Lib offensichtlich nicht wie erwartet funktioniert.

    Meine Lib sieht so aus:

    Source Code: DemoTest.lib

    1. ;
    2. ; Demo-Lib
    3. ;
    4. [CalcByte]
    5. $External InternInvertByte
    6. ; Byte manipulieren
    7. ; Byte wird in r24 erwartet
    8. CalcByte:
    9. MOV r20, r24 ; Byte nach r20 kopieren
    10. CALL InternInvertByte; Aufruf interne Routine
    11. MOV r24, r20; Rückgabe in r24
    12. Ret
    13. [End]
    14. [InternInvertByte]
    15. ; Byte wird in r20 erwartet
    16. InternInvertByte:
    17. NEG r20
    18. Ret
    19. [End]
    Display All
    In Zeile 6 wird auf die Routine InternInvertByte verwiesen, die von CalcByte benötigt wird.
    Ich gehe davon aus, dass der Compiler jetzt diese externe Routine ebenfalls einbinden sollte.

    Die Routine CalcByte soll von Bascom aus aufgerufen werden. Diese ruft dann intern die Routine InternInvertByte auf.
    Damit sie vom Compiler gefunden wird, ist die Routine in Zeile 6 mit $External angegeben.

    Mein Basic-Programm sieht nun so aus:

    BASCOM Source Code: Demo.bas

    1. '
    2. ' Demo
    3. ' Fehler beim Compilieren
    4. ' Beschreibung
    5. ' ------------
    6. ' Die Lib "DemoTest.lib" beinhaltet 2 Routinen.
    7. ' Routine 1: CalcByte(Byval a as Byte)
    8. ' Sie wird aufgerufen vom Bascom-Programm und übergibt den Parameter "a"
    9. ' an eine andere Routine innerhalb der Lib. Diese manipuliert den Parameter.
    10. ' Der Rückgabewert aus der 2. Routine wird in der 1. in r24 kopiert.
    11. ' Routine 2: InternInvertByte
    12. ' Sie wird intern, innerhalb der Lib von CalcByte aufgerufen.
    13. ' Hier wird das übergebene Byte negiert.
    14. ' Im Bascom_programm wird die Lib eingebunden und mit $External die Routine
    15. ' CalcByte angegeben
    16. ' Weiterhin wird die Routine CalcByte in Bascom deklariert.
    17. ' Problem:
    18. ' Fehlermeldung beim Compilieren:
    19. ' Error : 61 Line : 7 Label not found [INTERNINVERTBYTE], in File : C:\MCS\BASCAVR2083\LIB\DEMOTEST.LI
    20. ' Das Label ist jedoch in der Lib in Zeile 6 mit $External in der Routine CalcByte angegeben.
    21. ' Warum findet Bascom die interne Unter-Routine nicht?
    22. ' Was mache ich falsch?
    23. $Regfile = "m8def.dat"
    24. $HWStack = 30
    25. $SWStacK = 30
    26. $FrameSize = 40
    27. $Crystal = 8000000
    28. Config SubMode = New
    29. Config Base = 0
    30. $Lib "DemoTest.lib" ' Einbinden der Lib
    31. $External CalcByte ' nur CalcByte einbinden
    32. ' die interne Routine InternInvertByte
    33. ' soll von der Lib intern eingebunden werden
    34. Declare Sub CalcByte(Byreg r24 as Byte) ' Deklaration der aufzurufenden Sub in der Lib
    35. Dim a as Byte
    36. a = &h33
    37. Do
    38. a = &h33
    39. Call CalcByte(a)
    40. Loop
    Display All
    In Zeile 40 wird die Lib eingebunden, in Zeile 41 die aufzurufende Routine mit $External angegeben.
    Danach folgt noch die Deklaration der Routine CalcByte für den Aufruf.

    Wenn ich nun versuche zu compilieren, erhalte ich diesen Fehler:
    Error : 61 Line : 7 Label not found [INTERNINVERTBYTE], in File : C:\MCS\BASCAVR2083\LIB\DEMOTEST.LIB


    Die Fehlermeldung bezieht sich auf die interne Lib-Routine, von der offensichtlich das Label nicht gefunden wird.
    Das Label ist aber da. Auch die Blockbezeichnung [InternInvertByte] sind genau wie das Label betitelt.

    Was mache ich falsch?

    Übrigens lässt sich die Lib fehlerlos mit dem Lib-Manager compilieren.
    Entweder findet dieser das Label oder es wird nicht geprüft.

    Was ist da los?
    Wo liegt der Fehler?

    Benutze V2.0.8.3
  • So gehts:

    Source Code

    1. ; Demo-Lib
    2. [CalcByte]
    3. CalcByte:
    4. MOV r20, r24
    5. Call InternInvertByte
    6. MOV r24, r20
    7. Ret
    8. InternInvertByte:
    9. NEG r20
    10. Ret
    11. [End]
    Display All
    Es wäre ein Widerspruch wenn der Compiler gesagt bekommt "nimm nur Calcbyte" und der dann noch werweiswas anderes alles mitbringt. Da hätte ja gleich die ganze lib genommen werden können.
  • Pluto25 wrote:

    Es wäre ein Widerspruch wenn der Compiler gesagt bekommt "nimm nur Calcbyte" und der dann noch werweiswas anderes alles mitbringt. Da hätte ja gleich die ganze lib genommen werden können.
    Danke für deine Mühe.
    Ich sehe das aber anders.

    Schaue mal in die mcs.Lib an und suche mal nach dem (internen) Befehl _LPMByte.
    Den findest du in Zeile 1940.
    Der wird auch von verschiedenen Routinen aufgerufen.
    Zeile 1993, 2137, 2156, 2180 usw.

    Genau so etwas möchte ich in meiner Lib auch machen.

    Ich konnte in der mcs.lib nicht sehen, dass _LPMByte in jede Routine eingebaut wird, wo man ein Byte aus dem Flash lesen möchte.

    Oder anders gefragt.
    Was macht der Befehl $External labelname in der mcs.lib?
  • Die msc.lib scheint ein Sonderfall zu sein?
    $External _flash2ram z. B. geht auch ohne $lib "mcs.lib"
    Läßt sich compilieren aber schmiert ab - (vermutlih darf ich nicht einfach Call _flash2ram(2) anfordern)
    Gibt es ein Beispiel mit einer Lib deren Routinen nicht schon in Bascom vorhanden sind?

    Nimmt der Compiler nicht generell nur was nötig ist? Also auch ohne External?
    Da fällt mir z.B. die Port_remap ein die riesig groß ist aber nur ein paar Byte Flash benötigt.
  • Pluto25 wrote:

    Gibt es ein Beispiel mit einer Lib deren Routinen nicht schon in Bascom vorhanden sind?
    Das Beispiel siehst du im 1. Post.

    Pluto25 wrote:

    Nimmt der Compiler nicht generell nur was nötig ist? Also auch ohne External?
    Glaub ich nicht. Wozu gibt es denn dann den $External in den Lib's, wenn man ihn nicht braucht?

    Pluto25 wrote:

    Da fällt mir z.B. die Port_remap ein
    Diese Lib kenne ich nicht.
  • Schau dir mal die Lib "bigstrings.lib" an.

    Im Speziellen die Routine [_COPYMIDSTRING] und [_COPYSTRING].

    Die erste [_COPYMIDSTRING] ruft die externe Routine [_COPYSTRING] (in der gleichen Lib) auf.
    Da ist auch $EXTERNAL _COPYSTRING in der [_COPYMIDSTRING] angegeben.


    Ich verstehe das so, wenn man die routine _CopyMidString irgendwo im Code aufruft, erkennt der Compiler, dass auch noch die Routine _CopyString benötigt wird.


    Ohne $External würde die Routine fehlen.
  • Mitch64 wrote:

    Ohne $External würde die Routine fehlen.
    Auch son Sonderfall. Es funktioniert auch dann wenn die Routine [_COPYSTRING] vollständig aus der lib entfernt wird. Vermutlich gibt es sie auch schon innerhalb Bascom.
    Gibt es da irgendwo eine Übersicht welche Routinen vorhanden sind ?
    Viele der $External Einbindungen sind nicht in der jeweiligen Lib vorhanden (z.B. _ADJUST_PIN, _Byte2Str etc)
  • Die Groß-Kleinschreibung kat keine Auswirkung.
    Das habe ich eben ausprobiert.
    Und ein Space nach der eckigen Klammer zu ist bei mir auch nicht in der Lib.

    Zum Nachvollziehen hier also nochmal der gesamte Code im Angang.

    Übrigens das $External ist in der Lib (Anhang) nicht mehr groß geschrieben.

    Ich habe aber jetzt den Fehler gefunden.
    Vor den $External darf kein Space sein, es muss also ganz links stehen. Dann funktioniert es auch kleingeschrieben.

    Kannst du das bestätigen?
    Files
    • Demo_Lib.zip

      (1.74 kB, downloaded 3 times, last: )

    The post was edited 1 time, last by Mitch64 ().

  • Vorsichtig / Gründlich mit der Namenswahl. Das macht keine Fehlermeldung arbeitet aber total falsch:

    Source Code

    1. ;
    2. ; Demo-Lib
    3. ;
    4. [CalcByte]
    5. $ExTeRnAl _Byte2Str
    6. CalcByte:
    7. MOV r20, r24 ; Byte nach r20 kopieren
    8. ;CALL InternInvertByte; Aufruf interne Routine
    9. call _byte2str
    10. MOV r24, r20; Rückgabe in r24
    11. Ret
    12. [End]
    13. [_Byte3Str]
    14. ; Byte wird in r20 erwartet
    15. InternInvertByte:
    16. _Byte3Str:
    17. NEG r20
    18. Ret
    19. [End]
    Display All
    Solltest Du einen Namen wählen den es intern schon gibt wird er die interne Routine wählen wenn es in der lib nicht vorhanden (falsch geschrieben) ist; bzw den internen mit den in der lib vorhandenen ersetzen (wenn er richtig geschrieben ist)
    Was passiert mit den Routinen die den internen verwenden und dann einen neu definierten in einer Lib finden?
  • Du merkst es ja selber, dass es in Hinblick auf Lib-Erstellung viele offene Fragen gibt.

    Offiziell ist so gut wie nix Dokumentiert.
    Außer der Zugriff auf die Parameter, die von Bascom übergeben werden, also mit Declare Sub/Function angegeben sind mit einem kleinen Lib-Beispiel.

    Die ganzen Internas sind offiziell nicht dokumentiert. Zumindest nicht in der Bascom-Hilfe.
    Im Netz findet man auch nur wenig bis nix.

    Es ist nicht beschrieben, dass die Direktive $External auch für bzw. innerhalb von Lib's Gültigkeit hat, dass die Direktive dann ganz links in der Zeile stehen muss und die Parameter den Blocknamen oder vielleicht besser formuliert den Sektionsnamen entsprechen muss.

    Es ist auch nicht beschrieben, ob so ein Sektionsname ebenfalls ganz links in der Zeile stehen muss. Ebenso wenig, ob der Name dem Einsprungspunkt des Labels entsprechen muss oder ein freier Bezeichner sein darf.

    Es ist nicht beschrieben, was es mit dem Stern * vor einigen Zeilen auf sich hat. Manchmal auch *Basic:

    Es gibt keine Info's zu den Direktiven @sectic und @genus.

    Wie erzeugt man Variablen oder Arrays und Strings in einer Lib?

    Wie kann man Config xx=xx für eigene Libs erzeugen?

    Man kann solche Dinge teilweise zwar mit mühsamen Ausprobieren herausfinden, aber es gibt keine Gewähr, dass solche Regeln nach einem Update noch Gültigkeit haben.
    Man steht da also auf wackeligen Beinen.

    An der Stelle würde ich mir wünschen, dass solche Infos auch in die Bascom-Hilfe aufgenommen werden.
    Erstaunlich auch, dass der Lib-Compiler nicht anschlägt, wenn da etwas falsch angegeben ist, eine mit $External angegebene Sektion nicht vorhanden ist wird nicht als Fehler erkannt, auch nicht wenn man in der Lib @irgendwas schreiben kann anstelle von @sectic und@genus.
  • Mitch64 wrote:

    Erstaunlich auch, dass der Lib-Compiler nicht anschlägt, wenn da etwas falsch angegeben ist, eine mit $External angegebene Sektion nicht vorhanden ist wird nicht als Fehler erkannt,
    Vermutlich compiliert er nur die Mnemonics in Obj -Codes. Allein unbekannte/falsch geschriebene reklamiert er. Die Prüfung auf nicht (in der lib) vorhandene Externals übernimmt der Bascom Compiler.
    Das funktioniert auch lib übergreifend. In einer kann ein External angegeben werden das in einer anderen steht.

    The post was edited 1 time, last by Pluto25 ().

  • Pluto25 wrote:

    Vermutlich compiliert er nur die Mnemonics in Obj -Codes. Allein unbekannte/falsch geschriebene reklamiert er.
    Das glaube ich auch.

    Pluto25 wrote:

    Das funktioniert auch lib übergreifend
    Dem stimme ich auch zu.

    Aber ich hätte wenigstens eine Syntax-Prüfung der $External-Anweisung erwartet, entweder mit dem Lib-Compiler oder dem normalen Compiler.
    Offensichtlich wird die Anweisung vom Lexer/Scanner/Tokenizer (egal welcher Compiler) nicht erkannt, weil sie nicht am Zeienanfang steht,
    und deshalb die notwendige Routine nicht eingebunden.
    Das müsste aber einen Systax-Fehler ergeben oder zumindest eine Warnung dass die Anweisung links stehen muss.

    Wahrscheinlich macht der Comliper nur sowas wie

    BASCOM Source Code

    1. If UCase(Left$(QuellcodeZeile, 9)) = "$EXTERNAL" then
    2. ' dann enthaltene Sektionsnamen ermitteln und einbinden.
    3. End If
    Und das würde logisch dazu führen, dass die externe Routine nicht gefunden wird, weil ja nicht eingebunden.

    Ich will das jetzt nicht anmäkeln (weil kein Bug), aber schön ist das nicht!
    Sowas verhindert auch ein Stück weit, dass man keine strukturierten Lib's schreiben kann.
  • Mitch64 wrote:

    Wie erzeugt man Variablen oder Arrays und Strings in einer Lib?

    Wie kann man Config xx=xx für eigene Libs erzeugen?
    Vermutlich gar nicht. Sie müssen ja vorher bekannt sein damit der Stack entsprechend gesetzt wird. Oder die lib selbst muß sich darum kümmern (ohne mit Bascom zu kollidieren). Zwei Möglichkeiten gäbe es. Ein Dim Dummystring * Wunschspeicher oder Declare libsub(byval Dummy*xyz as String) wenn es im Stack landen soll.
    Beim Config sehe ich schwarz. die entsprechenden Constanten/Variablennamen sind im Compiler hinterlegt. Nirgendwo eine Anmerkung das sie erweitert werden könnten.
    Nun würde bei Dir ;) auch irgendwo stehen wie das Config auszufüllen ist. Da könnte dann natürlich stattdessen stehen : Benötigt werden Variable xyz, Konstante abc, etc.
    Bei den Display inc ist das ähnlich gelöst (Landscape/Portray)
    Weniger Schön wäre es es einfach zu lassen. Dann macht der Compiler eine Fehlermeldung jedoch u.U keinen Hinweis welche lib da was vermisst
    z.B. YwRobot_Lcd_i2c.lib
    Error : 5 Line : 1391 No more space for BIT [LCD_BACKLIGHT]
    Error : 93 Line : 1391 Variable not dimensioned [PCF8574_LCD]
    Error : 320 Line : 1391 [syntax error, token = '{']
    Kein gutes Beispiel. In dieser lib steht oben drinn das die beiden definiert werden müssen.
  • Pluto25 wrote:

    Vermutlich gar nicht.
    Doch das geht. Nur weil es eben nicht dokumentiert ist, weiß das keiner.
    Variablen sind im allgemeinen global (außer die locale in Subs).

    Pluto25 wrote:

    Beim Config sehe ich schwarz.
    Da haste vermutlich recht.

    Ein Stückweit kann man was in dem *.kfr-File machen (richtig geschrieben)?

    Ich denke, wie mal bekannt ist, was man alles in einem Lib machen kann, würde es viel mehr Leute geben, die sich mit Libs beschäftigen.
    Mit dem Ergebnis, dass man mehr Libs für Bauteile hätte und nicht immer selber was zusammenbauen muss.
  • Erst wollte ich mich hierzu nicht äüßern aber der BS-Faktor ist mir hier einfach zu hoch.

    Mitch64 wrote:

    Die ganzen Internas sind offiziell nicht dokumentiert. Zumindest nicht in der Bascom-Hilfe.
    Im Netz findet man auch nur wenig bis nix.
    ...irgentwie ein Paradoxon: "Internas sind offiziell nicht dokumentiert"... a_27_b277ca12
    Aber, deine Behaptungen stimmen nicht. Ein paar Beispiele:

    Mitch64 wrote:

    Es ist nicht beschrieben, was es mit dem Stern * vor einigen Zeilen auf sich hat.
    Doch, siehe Hilfe, $Lib.

    Mitch64 wrote:

    Es ist auch nicht beschrieben, ob so ein Sektionsname ebenfalls ganz links in der Zeile stehen muss. Ebenso wenig, ob der Name dem Einsprungspunkt des Labels entsprechen muss oder ein freier Bezeichner sein darf.
    Doch, siehe Hilfe Language Fundamentals. Da steht:

    - Line labels may begin in any column, as long as they are the first characters other than blanks on the line.
    - Blanks are not allowed between an alphabetic label and the colon following it.
    - A line can have only one label. When there is a label on the line , no other identifiers may be used on the same line. So the label is the sole identifier on a line.

    Dasselbe gilt für konsequent natürlich auch für "Sektionen", ist ja nichts anderes. Findet man in jeder Library. Einfach mal reinschauem und lernen.
    Da fällt mir ein: Sektion ist ein Terminus, den ich in diesem Bezug bisher nur von mir kenne... Gut, dann bin ich damit nicht alleine.



    Mitch64 wrote:

    Es gibt keine Info's zu den Direktiven @sectic und @genus.
    Doch im Netz...
    Ein Beispiel zu @genus, gefunden im mcselec.com Forum:

    Mark Alberts wrote:

    the @genus is not part of atmels assembler. it is a bascom specific enhancement.
    it will create the same delay as if you would use waitUS. And so it takes into account the clock frequency.



    Mitch64 wrote:

    Wie erzeugt man Variablen oder Arrays und Strings in einer Lib?
    Es liegt auf der Hand. Du musst schon *BASIC: bemühen. Erwarte nicht Gott weiß was Anderes. Wozu denn auch, damit's so richtig nach Assembler aussieht!? Schau dir Beispiele an. Das ist deine Quelle.



    Mitch64 wrote:

    Es ist nicht beschrieben, dass die Direktive $External auch für bzw. innerhalb von Lib's Gültigkeit hat,
    Aus der Hilfe: $external
    Instruct the compiler to include ASM routines from a library.
    +
    Schau in bestehende Libraries. $external über $external. Reingucken, lernen wie man es macht und weniger meckern.
    In der Hilfe unter ASM Librarys and add ons steht ausserdem: The bcd.lib and bin2bcd.bas demonstrate how to write a user lib. Im Klartext : Schau Dir Beispiele an.





    Mitch64 wrote:

    Man kann solche Dinge teilweise zwar mit mühsamen Ausprobieren herausfinden, aber es gibt keine Gewähr, dass solche Regeln nach einem Update noch Gültigkeit haben.
    Man steht da also auf wackeligen Beinen.
    Blödsinn. Wenn das so wäre, müsste alle Libraries ständig geändert werden und MCS würde allen mit entsprechenden Ambitionen das Leben schwer machen. Inklusive mir.



    Mitch64 wrote:

    Wie kann man Config xx=xx für eigene Libs erzeugen?
    Rhetorische Gegenfrage! Wo steht das man das man können sollen muss?!
  • Ich bemerke, dass du dir viel Mühe machst Bascom zu verteidigen.

    Und es ging im Grunde darum, dass $External in der Lib ganz links stehen muss, sonst funktioniert es nicht.
    Das hat mich einiges an Zeit gekostet, den Fehler zu finden.

    Und das steht definitiv nicht explizit in der Hilfe. Labels müssen auch nicht links beginnen, habe ich festgestellt. Warum also $External (so dachte ich).

    Ich habe außerdem nicht gemeckert, sondern festgestellt.

    Ich will hier aber nicht streiten.

    Wäre ich Entwickler würde ich sowas als konstruktive Kritik betrachten. Nicht als Gemecker.

    Bitte Thread schließen. Danke.