Ich lege auf einem Mega8 in Assembler einen RAM-Buffer der Größe SIZE an
mit
1
.section.bss
2
buffer:.skipSIZE
Um die Pointer-Berechnungen zu vereinfachen (nur im Register ZL und
nicht im Register ZH), würde ich gern sicherstellen, dass der gesamte
Buffer im Adressraum einer Seite liegt, d.h. hi8(buffer) und
hi8(buffer+SIZE-1) sollen gleich sein.
Wenn diese Bedingung nicht erfüllt ist, dann kann ich sie erzwingen,
indem ich die vorhandenen Variablen entsprechend manuell umstelle.
Wie kann ich aber beim Assemblieren/Linken mit avr-as automatisch
diese Bedingung überprüfen? Mein erster Ansatz war
1
.if(buffer/256)-((buffer+SIZE-1)/256)
2
.error"Pagewrap in Bufferadressen"
3
.endif
Dies wird mit dem Fehler "non-constant expression in .if statement"
quittiert, vermutlich weil die Festlegung der Adressen später erfolgt
als das .if ausgewertet wird.
Wo kann ich da ansetzen? Kann nicht sein, dass ich mit "avr-objdump -t"
und "grep" basteln muss?
.balign kenne ich, das funktioniert hier aber nicht:
(1) ich brauche nur eine Überprüfung zur Compilezeit; wenn die
fehlschlägt, würde ich die Bereiche von Hand vertauschen
(2) balign kann bestenfalls auf Vielfache von 8 alignen; um einen
Überlauf ins Hi-Byte sicher zu verhindern, müsste ich aber auf 256
alignen.
Wird sinnvoller sein, diesen Kampf mit dem Linker auszufechten. Mach
eine eigene Section für den Puffer und sorge dafür, das die entsprechend
liegt. Richtig gemacht spart das ausserdem Platz.
>.balign kenne ich, das funktioniert hier aber nicht:
So? Wieso nicht?
>(1) ich brauche nur eine Überprüfung zur Compilezeit; wenn die >fehlschlägt,
würde ich die Bereiche von Hand vertauschen
Wozu denn? Soweit ich Dich verstanden habe, möchtest Du, das der Bereich
aligned ist Mit balign erreichst Du das. Dann ist er auch aligned.
Du brauchst das nicht nochmal zu überprüfen (Wenn as an sich korrekt
arbeitet).
>(2) balign kann bestenfalls auf Vielfache von 8 alignen; um einen>Überlauf ins Hi-Byte sicher zu verhindern, müsste ich aber auf 256>alignen.
Das ist durchaus nicht der Fall. Lies noch mal nach.
Mmmh schrieb:
> Wozu denn? Soweit ich Dich verstanden habe, möchtest Du, das der Bereich> aligned ist Mit balign erreichst Du das.
Nein, ich möchte nur einen Übertrag im Hi-Byte der Adressen in diesem
Bereich ausschließen. Beispiel: ist der Bereich 0x40 Bytes lang, so sind
die Möglichkeiten
0x0200..0x023f erlaubt
0x0201..0x0240 erlaubt
...
0x02c0..0x02ff erlaubt
0x02c1..0x0300 nicht erlaubt
0x02c2..0x0301 nicht erlaubt
...
0x02ff..0x033e nicht erlaubt
0x0300..0x033f erlaubt
0x0301..0x0340 erlaubt
>Nein, ich möchte nur einen Übertrag im Hi-Byte der Adressen in diesem
Bereich ausschließen
Häh? In Deinen Beispielen bewertest Du doch bestimmte Alignments. Das
heisst jedes Argument von 0 bis 0xC0 würde das von Dir geforderte
Alignment ergeben, da es keinen Überlauf in das High-Byte ergäbe. Ergo
brauchst Du das Alignment nicht zu prüfen, sondern dieses eben nur mit
balign zu erzwingen. Worauf bezieht sich dann das "nein"?
Du bist doch mit balign dem Compiler insofern eben nicht ausgeliefert,
so das Du das Alignment nur prüfen könntest! Du kannst es ja erzwingen.
Also brauchst Du nicht zu prüfen!
Mmmh schrieb:
> Worauf bezieht sich dann das "nein"?
Auf "möchtest Du, dass der Bereich aligned ist".
> Häh? In Deinen Beispielen bewertest Du doch bestimmte Alignments. Das> heisst jedes Argument von 0 bis 0xC0 würde das von Dir geforderte> Alignment ergeben, da es keinen Überlauf in das High-Byte ergäbe. Ergo> brauchst Du das Alignment nicht zu prüfen, sondern dieses eben nur mit> balign zu erzwingen.
Wenn ich "balign N" verwende, dann werden 0 bis N-1 bytes eingefügt,
damit anschließend die nachfolgende Adresse kongruent 0 modulo N ist.
(Soweit ich das verstehe.)
Das hat mit obiger Anforderung nichts zu tun, weil die gewünschte
Adresse nicht mit einer modulo-Operation beschrieben werden kann.
>Wenn ich "balign N" verwende, dann werden 0 bis N-1 bytes eingefügt,>damit anschließend die nachfolgende Adresse kongruent 0 modulo N ist.>(Soweit ich das verstehe.)
Das sehe ich auch so.
Was ich da geschrieben habe ist falsch:
> Das heisst jedes Argument von 0 bis 0xC0 würde das von Dir geforderte> Alignment ergeben
Nicht jedes Argument würde passen.
Man müsste 0x40 als Argument nehmen.
Das könnte dann 0, 0x40, 0x80 oder 0xC0 als effektive Adresse ergeben.
In keinem Fall gäbe es einen Überlauf in das High-Byte.
>Das hat mit obiger Anforderung nichts zu tun, weil die gewünschte>Adresse nicht mit einer modulo-Operation beschrieben werden kann.
Wie man sieht geht das doch. Denn wenn die Adresse kongruent der Länge
ist, gilt das die Differenz zum Übertrag max der Länge entspricht. Was
klar ist, weil das ja gleichzeitig ein weiteres Vielfaches ergibt.
Ganz allgemein muss für das Argument von balign entweder die Länge
selbst, sofern diese eine Zweierpotenz ist oder die nächstgrösser
Zweierpotenz gewählt werden, wobei diese kleiner oder gleich der
Wertigkeit des Bits sein muss, in das die Addition (der Adresse) nicht
überlaufen darf.
Gut. Du hast nicht_ geschrieben das die Adresse aligned sein _soll .
Das war vielmehr ein Vorschlag um zu erreichen das die Adresse
garantiert nicht überläuft.
Da Du aber sonst keine Möglichkeit hast (ich weiss jedenfalls keine)
dies zu verhindern...
Mmmh schrieb:
> Ganz allgemein muss für das Argument von balign entweder die Länge> selbst, sofern diese eine Zweierpotenz ist oder die nächstgrösser> Zweierpotenz gewählt werden, wobei diese kleiner oder gleich der> Wertigkeit des Bits sein muss, in das die Addition (der Adresse) _nicht_> überlaufen darf.
Das wäre theoretisch eine Möglichkeit, die aber aus zwei Gründen nicht
praktikabel ist: (1) avr-as erlaubt bei .align nur Argumente <= 8 und
(2) es entstehen durch das Alignment Lücken im Adressraum, die sich
nicht für andere Daten nutzen lassen.
>(1) avr-as erlaubt bei .align nur Argumente <= 8
Oh, verdammt.
>(2) es entstehen durch das Alignment Lücken im Adressraum, die sich>nicht für andere Daten nutzen lassen.
Ja klar. Hättest Du vielleicht einen Tick früher schreiben sollen, dass
da noch eine Nebenbedingung ist. ;-)
Also muss man etwas direkter ran. Mit "." und if-endif selbst das
Alignment erzwingen. In dem Zuge dann nachher restliche Variablen in den
aufgefüllten Bereich setzen.
Im übrigen kannst Du natürlich, in dem Du "." überprüfst, Deinem
Ansatz folgen, falls Dir meiner zu kompliziert ist.
Ich habe das auf meinem Weg halt schon angewendet um gewisse
Ausrichtungen zu erwzingen. Z.B. ungeradzahlige, oder Positionen von
Variablen entsprechend ihrer Grösse zu bestimmen.
Mmmh schrieb:
> Im übrigen kannst Du natürlich, in dem Du "." überprüfst, _Deinem_> Ansatz folgen, falls Dir meiner zu kompliziert ist.>> Ich habe das auf meinem Weg halt schon angewendet um gewisse> Ausrichtungen zu erwzingen. Z.B. ungeradzahlige, oder Positionen von> Variablen entsprechend ihrer Grösse zu bestimmen.
Ein Beispiel für eine Überprüfung von . wäre sehr hilfreich. Ich habe
nach diesem Vorschlag
> Dies wird mit dem Fehler "non-constant expression in .if statement"> quittiert, vermutlich weil die Festlegung der Adressen später erfolgt> als das .if ausgewertet wird.
Ja, und zwar erst beim Linken. Deshalb mach das was A. K. gesagt hat:
> Wird sinnvoller sein, diesen Kampf mit dem Linker auszufechten. Mach> eine eigene Section für den Puffer und sorge dafür, das die entsprechend> liegt. Richtig gemacht spart das ausserdem Platz.
>Ja, und zwar erst beim Linken. Deshalb mach das was A. K. gesagt hat:>> Wird sinnvoller sein, diesen Kampf mit dem Linker auszufechten. Mach>> eine eigene Section für den Puffer und sorge dafür, das die entsprechend>> liegt. Richtig gemacht spart das ausserdem Platz.
Das wird dann tatsächlich über den Linker-Script laufen müssen.