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


von S. R. (svenska)


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)


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


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)


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


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)


Lesenswert?

S. R. schrieb:
> eine Implementation in C ist deutlich zu langsam.

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

von S. R. (svenska)


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!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.