Forum: Mikrocontroller und Digitale Elektronik [AVR] Wie Asm-funktion in C-Projekt ausrichten?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich möchte ein größeres Assemblermodul (avra) in ein gcc-Projekt 
einbinden und muss es daher erstmal auf avr-as umschreiben. Soweit, so 
nervig.

Bestimmte Teile des Codes müssen innerhalb eines 256 Byte großen Blocks 
liegen (der auch auf 256 Bytes ausgerichtet sein muss). Das gilt auch 
für einige Tabellen.

Der bisherige Code nutzt
  .org (PC + 255) & 0xFF00
und
  .if (high(block_end) != high(block_begin))
    .error "ERROR: block spans boundary, won't work"
  .endif
um das Alignment einzuhalten und auch zur Bauzeit zu prüfen. Innerhalb 
eines Object-Files ist die entstehende Adresse aber noch nicht bekannt, 
daher geht das dort nicht.

Wie kann ich diese Randbedingungen innerhalb eines Assemblermoduls 
sicherstellen? Geht das auch, ohne eigenes Linkerscript bauen zu müssen?

Ein bisschen Flash-Verschwendung wäre kein Problem, eine Implementation 
in C ist deutlich zu langsam.

Schönen Gruß

von Ludger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe vor Jahren mal eine AVRASM Implementierung von AES 
Verschluesselungsalgorithmen nach GCC portiert.

Alignment ist soweit ich es Erinnere auch dabei.

Beitrag "AES, Rijndael, WinAVR, Library"

von Johann L. (gjlayde) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> Bestimmte Teile des Codes müssen innerhalb eines 256 Byte großen Blocks
> liegen (der auch auf 256 Bytes ausgerichtet sein muss). Das gilt auch
> für einige Tabellen.
>
> Der bisherige Code nutzt
>   .org (PC + 255) & 0xFF00
> und
>   .if (high(block_end) != high(block_begin))
>     .error "ERROR: block spans boundary, won't work"
>   .endif
> um das Alignment einzuhalten und auch zur Bauzeit zu prüfen. Innerhalb
> eines Object-Files ist die entstehende Adresse aber noch nicht bekannt,
> daher geht das dort nicht.

Auf .org verzichten, das hat bei GNU andere Semantik, mit der du 
vermutlich nix anfangen kannst.

Stattdessen .balign 256 oder .p2align 8

Der Code beginnt dann bei entsprechendem Alignment.  Alternativ kann man 
das in ne eigene Section legen und das Alignment im ld-Skript festlegen.

Das .if funktioniert mit gas nicht, da der Assembler die Länge des 
Blocks nicht kennt bzw. nicht kennen kann; für eine entsprechende 
Assertion muss also ld-Skript her, etwa so:
1
; foo.sx
2
.text
3
.global main
4
.balign 256
5
main:
6
    nop
7
.global size_main
8
size_main = . - main
1
/* memory.x */
2
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
3
4
ASSERT (size_main == 2, "Blah size");
5
ASSERT (main % 256 == 0, "Blah align");
Das memory.x kommt mit auf die Kommandozeile, und ich würd auch 
empfehlen gas via avr-gcc zu verwenden:
1
$ avr-gcc -mmcu=atmega8 foo.sx memory.x -o foo.elf

von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
Wow, danke für die hilfreichen Hinweise!

Ludger schrieb:
> Alignment ist soweit ich es Erinnere auch dabei.

Hab ich reingeschaut. Da finden sich zwar Hinweise auf bestimmte 
Sections, aber die werden nicht weiter genutzt (zumindest habe ich 
nichts gefunden). Dafür waren andere nützliche Dinge drin.

Johann L. schrieb:
> Stattdessen .balign 256 oder .p2align 8

Ludgers Code nutzt ".align 8", ist das äquivalent?

Johann L. schrieb:
> Alternativ kann man das in ne eigene Section legen und
> das Alignment im ld-Skript festlegen.

Ich wusste nicht, dass man LD-Scripte (bzw. Ausschnitte davon) auf der 
Kommandozeile mitgeben kann. Das ist natürlich praktisch. Bisher bin ich 
davon ausgegangen, dass man immer ein vollständiges Script mitgeben 
muss. Hilft mir in diesem Fall zwar nicht, ist aber sehr nützlich.

Johann L. schrieb:
> Das .if funktioniert mit gas nicht, da der Assembler die Länge des
> Blocks nicht kennt bzw. nicht kennen kann

Hmm, warum eigentlich nicht? Ob Anfang und Ende innerhalb einer Page 
liegen, kann er natürlich nicht wissen, aber die Differenz beider 
Werte sollte ja konstant sein...

Bis auf die Asserts war das einfacher als gedacht. Immerhin.

von Johann L. (gjlayde) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> Johann L. schrieb:
>> Stattdessen .balign 256 oder .p2align 8
>
> Ludgers Code nutzt ".align 8", ist das äquivalent?

.align ist Target-abhängig .balign oder .p2align; daher bevorzuge ich 
explizit .balign oder .p2align.

> Johann L. schrieb:
>> Alternativ kann man das in ne eigene Section legen und
>> das Alignment im ld-Skript festlegen.
>
> Ich wusste nicht, dass man LD-Scripte (bzw. Ausschnitte davon) auf der
> Kommandozeile mitgeben kann.

Das Zeug muss schon in ne eigene Datei.

> Bisher bin ich davon ausgegangen, dass man immer ein vollständiges Script 
mitgeben muss.

Was der Compilertreiber (also avr-gcc) nicht kennt an Endung fasst er 
nicht an und geht davon aus, das es für den Linker ist.  Wenn dieser es 
auch nicht identifizieren kann wird's als ld-Script "Augmentation" 
verstanden und anders behandelt als -T.  Wenn man unbekannte Endungen 
verwendet wie .asm für Assembly und dem Treiber dies qua -x 
assembler-with-cpp mitteilt, muss man etwas aufpassen:
1
$ avr-gcc memory.x -x assembler-with-cpp foo.asm ...
oder
1
$ avr-gcc -x assembler-with-cpp foo.asm -x none memory.x ...
weil ansonsten memory.x als Assembly-Code interpretiert und der 
Assembler damit gefüttert wird (du könntest den Schnipsel z.B. auch 
assert.text nennen — das ".x" hat keine Funktion außer dass es eine 
unbekannte Endung darstellt).

> Hilft mir in diesem Fall zwar nicht, ist aber sehr nützlich.

Hilft schon, da kein komplettes Script gebraucht wird sondern das 
vorhandene quasi gepimpt werden kann mit den wenigen Zeilen.

> Johann L. schrieb:
>> Das .if funktioniert mit gas nicht, da der Assembler die Länge des
>> Blocks nicht kennt bzw. nicht kennen kann
>
> Hmm, warum eigentlich nicht?

Jump-Relaxing des Linkers: Wenn ein CALL in Quelle zu einem RCALL wird, 
kann der Assembler das nicht wissen, und damit auch nicht der Wert von 
Label-Differenzen berechnen. Der Assembler sieht den Code der 
Input-(Sub)Section schlicht als als Blob.  Wie der Assembler mit 
Label-Differenzen umgeht ist target- und evtl. auch schalterabhängig.

von Stephan (Gast)


Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> eine Implementation in C ist deutlich zu langsam.

oh oh.... das könnte hier interessant werden.

von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
>> Ludgers Code nutzt ".align 8", ist das äquivalent?
> .align ist Target-abhängig .balign oder .p2align;
> daher bevorzuge ich explizit .balign oder .p2align.

Gekauft.

Dann fiel mir gestern noch auf, dass der gleiche Code plötzlich nicht 
mehr in den vorgesehenen Platz passte, weil avra natürlich alles in 
Flash-Worten rechnet statt in Bytes. Also muss ich die Blöcke auf 512 
Bytes ausrichten und bei LPM aufpassen.

Johann L. schrieb:
> Hilft schon, da kein komplettes Script gebraucht wird sondern das
> vorhandene quasi gepimpt werden kann mit den wenigen Zeilen.

Ja, das ist verdammt nützlich. Danke für die Erklärung!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.