Hallo,
hab folgendes Problem in Bascom:
ich möchte den Data-Header auslesen, exakt 7 Bytes, es soll aber mit der
Variablen i ein beliebiger Header ausgelesen werden.
Kann die Stringlänge beim Lesezugriff beschränkt werden?
Schönen Abend,
danke für das Feedback - also mit reinen Bytes ist es mühsam.
es sind Strings für RTTTL-Klingeltöne, die erste Sequenz ist dabei der
Name des Liedes:
z.B.
1
Musik:
2
Data"Pac Man :d=4,o=5,b=112:32b,32p,32b6,32p,32f#6,32p,32d#6,32p,32b6,32f#6,16p,16d#6,16p,32c6,32p,32c7,32p,32g6,32p,32e6,32p,32c7,32g6,16p,16e6,16p,32b,32p,32b6,32p,32f#6,32p,32d#6,32p,32b6,32f#6,16p,16d#6,16p,32d#6,32e6,32f6,32p,32f6,32f#6,32g6"
Mit Hilfe von strlookup möchte ich jeweils den Songtitel zu einer
Songnummer ausgeben.
Hab schon mit loadlabel versucht, aber der liefert mir nur die
Startadresse von Musik, nicht aber die Adresse zu einer beliebigen
Songnummer..
So bleibt mir nichts anderes übrig, als die max. 255 Zeichen in eine
strtemp-Variable (dim strtemp als string*255) zu laden und dann die
ersten 7 Zeichen abzuschneiden..
dumm eigentlich, aber es dürfte nicht anders gehen.
Bascom ist zwar sehr gut, aber die Pointer vermisse ich immer mehr...
>> Mit Hilfe von strlookup möchte ich jeweils den Songtitel zu einer> Songnummer ausgeben.
OK.
Was spricht dagegen, pro Song einfach 2 Data-Zeilen zu benutzen?
Der Song mit der Nummer i beginnt dann beim Data mit der Nummer 2*i.
Wobei unter 2*i der Titel zu finden ist und die Songbeschreibung unter
2*i+1
(i bei 0 beginnend; weiss nicht, wie das bei BASCOM geregelt ist.
Schlimmsten Falls muss man dann eben noch einmal 1 dazuzählen, wenn da
bei 1 angefangen wird zu zählen)
Und wenn ich mir da die Daten so ansehe, dann scheint es da noch eine
Unterteilung zu geben. -> 3 Data Zeilen pro Song.
Guten Morgen,
ja - danke für die Tipps, mein Parser zerlegt den String dann zwar
ohnedies in die 3 Teile und es ist sicher ein "workaround" mit den 3
Data-Zeilen, aber ich wollte eine "echte" Lösung:
Zwei Schwächen gibts hier in Bascom:
1) ich kann nicht die Startadresse der Datazeile finden, so quasi ein
Befehl lookupadr fehlt
2) wenn die Variable kürzer ist als der Data-String, wird einfach der
nachfolgende Speicher überschrieben.
Da ist schon das Beispiel von Mark aus der Hilfe gefährlich, er nimmt
zwar Original Idx=0, aber bei Idx=2 "krachts":
1
$hwstack=32
2
$swstack=10
3
$framesize=40
4
DimSAsString*4,IdxAsByte
5
Idx=2:S=Lookupstr(idx,Sdata)
6
PrintS
7
PRINTIDX'ist116!!
8
End
9
Sdata:
10
Data"This","is","a test"
Wenn ich für IDX=2 nehme, werden - obwohl S nur mit 4 Byte definiert ist
- 5 Bytes angezeigt (und die nachfolgende Variable wird überschrieben)
Danach hat Idx den Wert 116 (den Ascii-Code von t = letzter Buchstabe
von "a test") !!!
Das mag was für Trickprogrammierer sein - aber nix für
Otto-Normalprogrammierer.
Manfred S. schrieb:> Das mag was für Trickprogrammierer sein - aber nix für> Otto-Normalprogrammierer.
Array Overflows sind nichts für Trick-Programmierer, sondern das ist bei
Null-terminierten Strings so, dass nachfolgende Variablen überschrieben
werden können.
Die Größeninformation der Variablen ist nur zur Kompilierzeit bekannt.
Wenn eine Bereichsüberprüfung stattfinden soll, dann muss der User a)
diese Information dem Code zur Verfügung stellen und b) entsprechenden
Code zum Schutz vor Bereichsüberprüfung selbst bereitstellen.
Die Verwendung von Lookupstr() um sich durch solche Monsterstrings
durchzuhangeln ist sowieso maximal ineffektiv.
Statt einen String mit 'ner Riesenzeile zu laden und damit sowohl 'ne
Menge SRam zu benutzen, als auch eine unnötige Kopieraktion zu haben,
schreit sowas nach einem Parser, der den Flash Zeichenweise durchgeht.
Es gibt dazu Bascom-Befehle, welche die Adresse des Labels und damit des
Strings ermitteln können und es gibt Befehle um aus dem Flash zu lesen.
Das ist dann der gewünschte Zeiger.
Effektiveren Zugriff auf die einzelnen Strings könnte man auch über
einen Label-Index machen.
1
$Regfile = "m32def.dat"
2
$Crystal = 8000000
3
$hwstack = 40
4
$swstack = 16
5
$framesize = 32
6
$baud = 9600
7
8
dim str_ptr as word
9
dim rtd_flash_byte as byte
10
11
restore lbl_linklist
12
13
Do
14
read str_ptr
15
if Str_Ptr = 0 then
16
restore lbl_linklist
17
else
18
rtd_flash_byte = cpeek(str_ptr)
19
while rtd_flash_byte <> 0
20
print chr(rtd_flash_byte) ;
21
incr str_ptr
22
rtd_flash_byte = cpeek(str_ptr)
23
wend
24
print
25
Loop
26
end
27
28
lbl_linklist:
29
adr2 lbl_1
30
adr2 lbl_2
31
adr2 lbl_3
32
adr2 lbl_4
33
adr2 lbl_5
34
data 0%
35
36
lbl_1:
37
data "This"
38
lbl_2:
39
data "is"
40
lbl_3:
41
data "my"
42
lbl_4:
43
data "Hello"
44
lbl_5:
45
data "World"
Dieser Code läss sich im Simulator ausprobieren.
Und auch Otto-Normalprogrammierer darf seine graue Grütze benutzen, um
alle Möglichkeiten der jeweiligen Programmiersprache auszunutzen. :D
Hallo,
das mit ADR2 ist super!
Das hätte ich schon oft brauchen können, hab dafür immer
"Select-Case und loadlabel" verwendet
Dein Code funktioniert (bis auf das fehlende EndIf ;-))
Hab jetzt eine Sub-daraus gebaut, die einen String beliebiger Länge
ausliest.
Kann man das auch als Funktion mit String-Rückgabe schreiben?
Da scheitere ich noch
Manfred S. schrieb:> Dein Code funktioniert
Ja, wusste ich, da's getestet war.
> (bis auf das fehlende EndIf ;-))
Ging unbeabsichtigt beim Einfügen/Editieren verloren.
> Kann man das auch als Funktion mit String-Rückgabe schreiben?
Locale Variablen landen im Frame, der muss deshalb groß genug sein,
$framesize entsprechend anpassen.
Der globale String mit Overlay würde ggf. wirtschaftlicher arbeiten, da
dort nicht nochmal vom Frame umkopiert werden muss.
Hallo, Mahlzeit,
super - ja das klappt -
hab das Ganze noch etwas "verfeiner" - naja zumindest im Simulator
läufts
(bin selbst überrascht, dass es funktioniert ;-))
Ich weiß jetzt nicht, ob das noch etwas Performance bringt.
Manfred S. schrieb:> Ich weiß jetzt nicht, ob das noch etwas Performance bringt.
Du sparst die Kopieraktion. Aber so richtig schnell ist's nicht.
Da Du ohne Trickprogrammiererei auskommen willst, ist das dann
natürlich nix für Dich: :D
1
$regfile = "m32def.dat"
2
$Crystal = 8000000
3
$hwstack = 40
4
$swstack = 40
5
$framesize = 64
6
$baud = 9600
7
8
$external _LookUpStr
9
$external _Lpmbyte
10
Dim idx As Byte
11
Dim lng As Byte
12
Dim lup_str As String * 20
13
14
idx = 2
15
lng = 20
16
17
loadwordadr lbl_block
18
!LDS R24, {idx}
19
!CLR R25
20
!CALL _LookUpStr
21
loadadr lup_str , X
22
!LDS R22, {lng}
23
!loop:
24
!CALL _Lpmbyte
25
!BREQ str_end
26
!ST X+, R0
27
!DEC R22
28
!BRNE loop
29
!str_end:
30
!CLR R22
31
!ST X, R22
32
33
Print lup_str
34
35
End
36
37
lbl_block:
38
data "This"
39
data "is"
40
Data "my Data is longer than 10 chars"
41
Data "Hello this is longer than 20 chars"
42
data "World"
Das entspricht der normalen Vorgehensweise des Lookupstr(), also sich
über die Stringendzeichen durchzuhangeln. Schlägt aufgrund des
Assembleraufbaus natürlich auch eine Indexliste.
Und noch'n Hinweis; die Strings dürfen hier innerhalb des Blocks keine
weiteren Labels haben, denn dann kann's sein, dass der Compiler auf Word
aligned und eine 0 einfügt, die dann falsch interpretiert würde.
Sorry, bin erst jetzt zum Analysieren gekommen -
muss sagen, einfach genial - jetzt brauch ich auch keine Labels mehr und
das ist exakt die Funktion, die ich benötigt habe.
Hab mir auch die dazugehörigen Routinen in der mcs.lib angesehen, da
wird ja Bascom noch viel interessanter.
Der Assembler dieser Harvard-Architektur ist schon genial und viel
einfacher als bei den Klassikern 6502, 8080 usw. die Pointer sind hier
schön verständlich..
Ist zwar offtopic:
Wo gibts mehr Infos bzw. gute Tutorials, welche Register Bascom belegt
und welche frei sind? Da muss ich unbedingt tiefer einsteigen