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ß
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"
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 |
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.
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.
S. R. schrieb: > eine Implementation in C ist deutlich zu langsam. oh oh.... das könnte hier interessant werden.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.