Forum: Mikrocontroller und Digitale Elektronik ARM Cortex M4 Assembler


von chris_ (Gast)


Lesenswert?

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?

von Jim M. (turboj)


Lesenswert?

Lade doch selbst: infocenter.arm.com,
fürs ARM ARM (kein Schreibfehler) wollen die IIRC Deine Email haben.

von (prx) A. K. (prx)


Lesenswert?

Schon auf die Idee gekommen, an der Quelle zu suchen? Bei ARM.

von Horst V. (hoschti)


Lesenswert?

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.

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

>Das könnte schon etwas Licht in Deine Finsternis bringen.

Leider nicht.

von Horst V. (hoschti)


Lesenswert?

Da war ich wohl zu ungenau. Ohne das www geht's. Sorry!

Sind "nur" 650 Seiten.

: Bearbeitet durch User
von chris_ (Gast)


Lesenswert?

>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?

von Stefan F. (Gast)


Lesenswert?

chris_ schrieb:
> 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.
https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html#Using-Assembly-Language-with-C

von chris_ (Gast)


Lesenswert?

>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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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

von PittyJ (Gast)


Lesenswert?

Der gcc arbeitet auch mit Assembler Files .s
Ich benutze das bei einem Bare-Metal Projekt für den Startup-Code.

https://stackoverflow.com/questions/7190050/how-do-i-compile-the-asm-generated-by-gcc

gcc -c file.s

von foobar (Gast)


Lesenswert?

> Hat jemand Beispielfiles in der Form  "asmBeispiel.c" File das eine
> Funktion im "asmBeispiel.s" File aufruft?

Einfach als extern declarieren und aufrufen:
1
   extern int foo(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):
1
   ...
2
   .global foo
3
foo:
4
   lsls r0,r0,#1
5
   bx   lr
6
   ...

von chris_ (Gast)


Lesenswert?

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.
1
#include <stdint.h>
2
3
// CPU_CLK=64MHz
4
void delay(uint32_t ms)
5
{
6
  int32_t n;
7
  for(n=0;n<ms;n++);
8
}
9
10
int main(void) 
11
{
12
  delay(1000);
13
}

von chris_ (Gast)


Lesenswert?

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" ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

Uhh ... gleich der erste Fehlschlag.
1
   .global asmDelay
2
3
asmDelay:
4
5
   ldr r0,=1000
6
7
   bx   lr

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

Der Linker gibt doch zusammen mit der Fehlermeldung gleich einen 
Hilfe-Link aus der das Problem beschreibt - Mann ... :-(

von chris_ (Gast)


Lesenswert?

>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.

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

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:
1
@ https://www.mikrocontroller.net/articles/ARM-ASM-Tutorial
2
@ https://stackoverflow.com/questions/28669905/what-is-the-difference-between-the-arm-thumb-and-thumb-2-instruction-encodings
3
4
    .cpu cortex-m4
5
6
    .syntax unified
7
    .thumb_func
8
    .global asmDelay
9
10
asmDelay:
11
    
12
    nop
13
14
    ldr r0,=1000
15
16
    bx   lr

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

chris_ schrieb:
> Mir ist unklar, wie der Prozessor daraus die 1000 ( 0x3E8 ) zusammen
> setzt.

"Modified immediate constants in Thumb instructions"

> 0xF44F707A
>
> d.h.
> i=1
> imm4=F
> imm3=7
> imm8=7A

Nö. Variante T2: i:imm3:abcdefgh = 1:111:01111010
i:imm3:a = 11110 => 0... 1b cdefgh00 = 11.1110.1000

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

F44F ist das T2 Encoding und wie das geht steht in 4.2.1 "Shifted 8-bit 
values".

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

> 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.

von foobar (Gast)


Lesenswert?

> 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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Kai (Gast)


Lesenswert?

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.

von rbx (Gast)


Lesenswert?

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 chris_ (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

chris_ schrieb:
> Himmel Herrgott ist das aufwendig!

Ja, wer mit Panel-Schaltern in Maschinencode programmiert, tut sich mit 
einer alten PDP-11 leichter. ;-)

von chris_ (Gast)


Lesenswert?

Kann man auf einen im Assemblerfile definierten Speicherbereich von der 
C-Seite zugreifen?
1
filterData:
2
    .word 4321

von Stefan F. (Gast)


Lesenswert?

(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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
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.