Ich suche Unterlagen zur Übersetzung des Assembler Codes in das
Binär-Format.
Früher war in der Befehlsbeschreibung der Prozessormanuals immer auch
das Bitfeld der Befehlskodierung enthalten, so dass man sehen konnte,
welche Bits z.B. für die Registerauswahl verwendet wurden.
Hat jemand Unterlagen für den Thumb2 Instruktionssatz?
Die Suchmaschine meiner Wahl liefert bei "thumb2 instruction set"
ziemlich weit oben den folgenden Link:
www.class.ece.iastate.edu/cpre288/resources/docs/Thumb-2SupplementRefere
nceManual.pdf
Das könnte schon etwas Licht in Deine Finsternis bringen.
>Da war ich wohl zu ungenau. Ohne das www geht's. Sorry!
Danke. Hat funktioniert und es steht auch drinnen, was ich suche.
Apropos:
Weiß jemand, wie man aus dem GCC einen Assembler Abschnitt aufruft und
wie die Parameterübergabe aussieht?
>Mit Inline Assembler kannst du alles so aufrufen, wie es dir beliebt.
Ich will keinen Inline Assembler verwenden. Ich mag die Syntax nicht.
Hat jemand Beispielfiles in der Form "asmBeispiel.c" File das eine
Funktion im "asmBeispiel.s" File aufruft?
chris_ schrieb:> wie die Parameterübergabe aussieht?
Reichlich komplex übrigens. Die Idee dabei ist, dass man dem Compiler
bei seinen Optimierungen möglichst nicht im Weg herum steht. Daher
deklariert man erst einmal normale Variablen im umgebenden C-Code, und
diese bekommen dann im inline asm statement "constraints", d.h. man
beschreibt, welchen Randbedingungen diese unterliegen, damit der mit
ihnen realisierte Assemblercode noch funktioniert. Dadurch ist der
Compiler ähnlich wie bei Optimieren eines normalen Kompilats in der
Lage, die Daten in Registern möglichst effizient zu nutzen. Geht
natürlich nur, wenn man ihm auch die Freiheit dafür lässt, d.h.
möglichst auch Zwischenergebnis-Register in dieser Form deklarieren,
statt einfach feste Annahmen für diese zu treffen und sie dann alle stur
in die "clobber"-Liste zu knallen.
> Hat jemand Beispielfiles in der Form "asmBeispiel.c" File das eine> Funktion im "asmBeispiel.s" File aufruft?
Einfach als extern declarieren und aufrufen:
1
externintfoo(int);
2
3
...
4
printf("foo(2)=%d\n",foo(2));
5
...
Der Assemblercode muß das Symbol auch entspr exportieren und natürlich
die ABI berücksichtigen (z.B. r0 ist erste Parameter und Rückgabewert):
Danke für die nützlichen Hinweise.
Ich habe mir überlegt, erst einmal mit einem sehr einfachen Beispiel
anzufangen und folgende delay-Funktion als Assembler Funktion zu
realisieren ( und die Laufzeiten mit dem Debugger auszumessen ).
Falls jemand schon weiß wie es geht, darf es gerne geposted werden.
Ich sehe gerade, hier im MC-Netz gibt es ein ARM-ASM Tutorial:
https://www.mikrocontroller.net/articles/ARM-ASM-Tutorial
Als erstes sehe ich:
As the starting point for any calculation, some specific values need to
be put into the registers. The easiest way to do that is:
ldr r0, =123456789
The number 123456789 will be encoded as part of the program, and the
instruction lets the processor copy it into the register “r0”. Any
number and any register in the range r0-r13 can be used instead.
Gibt es beim ARM-Assembler kein "load immediate" ?
chris_ schrieb:> Gibt es beim ARM-Assembler kein "load immediate" ?
Ist halt 'ne RISC-Maschine. Bei den 16-Bit-Thumb-Befehlen, wie viele
Bits "immediate" würdest du denn erwarten?
chris_ schrieb:> und die Laufzeiten mit dem Debugger auszumessen
Muss übrigens nicht sehr deterministisch sein (vor allem nicht, wenn
Caches ins Spiel kommen). Für ein grobes "verzögere mal mindestes <N>
Mikrosekunden" geht's, genauer mit einem Timer.
chris_ schrieb:> Gibt es beim ARM-Assembler kein "load immediate" ?
Doch. Aber versuch mal, in einem 16 oder 32 Bit breiten Befehl, eine 32
Bit breite Konstante unterzubringen. Weshalb es ein paar Varianten dafür
gibt. Obige arbeitet PC-relativ.
Bisschen Wasserkopf im Asm-File ist schon erforderlich. Orientiere dich
grob an dem, was der Compiler als Asm-File auswirft. Und schau nach, was
das jeweils bedeutet.
Per Default erzeugt der Assembler klassischen ARM Code (Arm-Mode),
keinen Thumb Code. Mit dem kann der Cortex M4 aber nichts anfangen.
>Der Linker gibt doch zusammen mit der Fehlermeldung gleich einen>Hilfe-Link aus der das Problem beschreibt - Mann ... :-(
Ja, aber auf keinen Fall solltest du die Lösung für das Assembler-File
hin schreiben, sonst könnte noch jemand die Nützlichkeit des MC-Netz mit
der von Stack-Overflow verwechseln. Es soll ja schließlich jeder zwei
Stunden nach dem richtigen Setup suchen müssen.
A.K. schrieb
>chris_ schrieb:>> Gibt es beim ARM-Assembler kein "load immediate" ?>Doch. Aber versuch mal, in einem 16 oder 32 Bit breiten Befehl, eine 32>Bit breite Konstante unterzubringen. Weshalb es ein paar Varianten dafür>gibt. Obige arbeitet PC-relativ.
Der Assembler scheint "ldr" ( load register ) in ein mov umzuwandeln.
Die Kodierung des Befehls ist dann
0xF44F707A
d.h.
i=1
imm4=F
imm3=7
imm8=7A
Mir ist unklar, wie der Prozessor daraus die 1000 ( 0x3E8 ) zusammen
setzt.
Mein aktueller Code:
von Jörg W. (dl8dtl) (Moderator) Benutzerseite
13.02.2021 18:48
>chris_ schrieb:>> Ich will keinen Inline Assembler verwenden. Ich mag die Syntax nicht.>Dein Problem. Die Syntax muss man nicht mögen :), sondern sie soll>optimalen Code gestatten.>Was du suchst, ist wohl eher das ABI. Da gibt's meines Wissens bei ARM>mehr als eins. Cortex-M4 klingt nach EABI.>https://stackoverflow.com/questions/8060174/what-are-the-purposes-of-the-arm-abi-and-eabi
Der Parameter für die Delay-Funktion scheint in R0 zu stehen ... ich
hab's einfach mal so verwendet.
Vielleicht könnte man die Parameterübergabe vereinfachen, wenn man immer
einen Pointer auf ein uint32_t Array übergibt und dann nur die Inhalte
in der Assembler-Routine ausliest und die Ergebnisse dort
hineinschreibt.
Bei Delay-Routinen dieser Art empfehle ich Selbstkalibrierung beim
Programmstart, statt einmaliger Handkalibrierung, denn jede Änderung am
Prozessor, z.B. durch Taktfrequenz, Cache, Prefetch, Waitstates,
Mondphase, ... kann die Laufzeit ändern. Auch Code-Alignment kann es
beeinflussen.
Also: Beim Programmstart diese Routine einmalig laufen lassen und die
Laufzeit davon per (Tick-)Counter messen. Daraus einen
Multiplikationsfaktor ableiten, der bei künftigen Delays eingerechnet
wird. Dann hat man nur noch einen Parameter, nämlich die Taktfrequenz
vom Counter.
> Vielleicht könnte man die Parameterübergabe vereinfachen, [...]
Die ABI musst du dir eh durchlesen - neben der Parameterübergabe sind ja
auch ne Latte anderer Sachen festgelegt, die du berücksichtigen musst.
> Bei Delay-Routinen dieser Art empfehle ich Selbstkalibrierung beim> Programmstart,
Selbst das ist ziemlich fruchtlos - wenn da nen anderer Busmaster
zwischenfunkt (DMA, anderer Core), stimmt wieder nichts.
Für sowas gibts den SysTick.
foobar schrieb:> Selbst das ist ziemlich fruchtlos - wenn da nen anderer Busmaster> zwischenfunkt (DMA, anderer Core), stimmt wieder nichts.
Zumindest stimmt die Mindestzeit, denn beim Start kann man sich eine
Phase aussuchen, in der niemand stört. Dass Delays aus Programmschleifen
nach oben variieren können, ist klar und sollte beachtet werden.
> Für sowas gibts den SysTick.
Klar. Wenn man sowas hat.
Dafür ist das prinzipielle Verfahren zur Laufzeit der Delays
unabhängig von jedweden speziellen Ressourcen, wie eben dem Systick.
Weshalb das auch schon bei Architekturen wie ARM7 funktionierte. Kann
man das dann noch über eine RTC kalibrieren, ist auch die Taktfrequenz
aus dem Spiel.
Vorsicht übrigens bei der onlineseite von Keil, die unter anderem die
SIMD Intrinsics beschreibt. Hab dort schon 3 Fehler entdeckt.
Man sollte sich besser auf das instructionset Dokument von Arm
verlassen.
Horst V. schrieb:> Die Suchmaschine meiner Wahl liefert bei "thumb2 instruction set"> ziemlich weit oben den folgenden Link:> www.class.ece.iastate.edu/cpre288/resources/docs/Thumb-2SupplementRefere> nceManual.pdf>> Das könnte schon etwas Licht in Deine Finsternis bringen.chris_ schrieb:>>Das könnte schon etwas Licht in Deine Finsternis bringen.>> Leider nicht.
aber wenn man den link selber in die Suchmaschine eingibt..
http://class.ece.iastate.edu/cpre288/resources/docs/Thumb-2SupplementReferenceManual.pdf
(aber das ist alt..)
Außerdem kann man echt Zweifel haben: RISC? aber drumherum darfs ein
wenig mehr Truthahn sein, bzw. ein wenig undokumentiert stört auch
nicht?
Gut, wenn man schon einen Debugger, oder ein paar Hexfiles (und ein
Tutorial) parat hat und gut, dass es das µc-forum gibt ;) .
(prx) A. K. schrieb:> Aber versuch mal, in einem 16 oder 32 Bit breiten Befehl, eine 32> Bit breite Konstante unterzubringen. Weshalb es ein paar Varianten dafür> gibt. Obige arbeitet PC-relativ.
DAS ist mal interessant/spannend, aber hinterlässt ein großes ?
von foobar (Gast)
14.02.2021 08:10
>F44F ist das T2 Encoding und wie das geht steht in 4.2.1 "Shifted 8-bit>values".
Himmel Herrgott ist das aufwendig!
A.K. schrieb:
>Nö. Variante T2: i:imm3:abcdefgh = 1:111:01111010>i:imm3:a = 11110 => 0... 1b cdefgh00 = 11.1110.1000
chris_ schrieb:> Himmel Herrgott ist das aufwendig!
Ja, wer mit Panel-Schaltern in Maschinencode programmiert, tut sich mit
einer alten PDP-11 leichter. ;-)
(prx) A. K. schrieb:> Bei Delay-Routinen dieser Art empfehle ich Selbstkalibrierung beim> Programmstart,
Erinnert mich an die Einführung des Pentium 2, an dem sämtliche Borland
Pascal Programme mit einem Abbruch scheiterten, weil die CPU zu schnell
wurde.
Zum Glück hat man das Problem bei µC eher selten. Da programmiert man
seltener für so einen wilden ständig mutierenden Zoo von Hardware, wie
beim PC.
Stefan ⛄ F. schrieb:> Zum Glück hat man das Problem bei µC eher selten. Da programmiert man> seltener für so einen wilden ständig mutierenden Zoo von Hardware, wie> beim PC.
Die Probleme sind ähnlich, wenn man nicht auf dem ziemlich einfach
reproduzierbaren Niveau der AVRs bleibt.
Allein wenn man sich durch die diversen STM32 Familien mit
unterschiedlichen Flash-Konfigurationen bewegt, hinsichtlich Caching und
Waitstates abhängig von der Taktfrequenz, kann das ein Thema sein.
Selbstkalibrierung vermeidet dann Fehler. Auch schon die Verschiebung
des Codes der Schleife um ein paar Bytes kann Folgen haben.