Forum: Mikrocontroller und Digitale Elektronik generierten Code verstehen STM32F4


von Christoph K. (chriskuku)


Lesenswert?

Ich versuche, den generierten Assemblercode zu verstehen:
1
 ----------------------------------------------------------------------
2
  90                    Setup_UART:
3
  91                    @ ----------------------------------------------------------------------
4
  92
5
  93                            @ Enable the CCM RAM and all GPIO peripheral clock
6
  94 15ea 1949                  ldr r1, = RCC_AHB1ENR
7
  95 15ec 1948                  ldr r0, = BIT20+0x1FF
8
  96 15ee 0860                  str r0, [r1]
9
  97
10
  98                            @ Set PORTB pins in alternate function mode
11
  99 15f0 1949                  ldr r1, = GPIOB_MODER
12
 100 15f2 0868                  ldr r0, [r1]
13
 101 15f4 50F42000              orrs r0, #0x00A00000
14
 102 15f8 0860                  str r0, [r1]

Wieso wird in Zeile 94 nur ein 0x1949 generiert, wo doch
1
 .equ RCC_BASE        ,   0x40023800
2
 .equ RCC_AHB1ENR     ,   RCC_BASE + 0x30

also in dem generierten Code doch die Daten 0x40023830 irgendwo 
auftauchen müßten? Ähnlich auch in allen Zeilen, wo 32bit immediate 
Daten vorkommen?
Liegt das am Thumb-Instruction set?

Grüße
Christoph

von Andreas B. (abm)


Lesenswert?

'.pool' fehlt!

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


Lesenswert?

Bei einer 32-bit-RISC-Maschine gibt's (normalerweise) keine 
32-bit-Direktoperanden.

Üblich bei ARM ist es, die entsprechenden Werte PC-relativ hinter den 
Code der Funktion zu legen.

von benutzt_aus_zwingenden_Gründen_assembler (Gast)


Lesenswert?

Jörg W. schrieb:
> Bei einer 32-bit-RISC-Maschine gibt's (normalerweise) keine
> 32-bit-Direktoperanden.
>
> Üblich bei ARM ist es, die entsprechenden Werte PC-relativ hinter den
> Code der Funktion zu legen.

Ah, danke. Verstehe immer mehr. :)

von benutzt_aus_zwingenden_Gründen_assembler (Gast)


Lesenswert?

Andreas B. schrieb:
> '.pool' fehlt!

Bitte erklären.

von Christoph K. (chriskuku)


Lesenswert?

Jörg W. schrieb:
> Bei einer 32-bit-RISC-Maschine gibt's (normalerweise) keine
> 32-bit-Direktoperanden.
>
> Üblich bei ARM ist es, die entsprechenden Werte PC-relativ hinter den
> Code der Funktion zu legen.

PC-relativ: wo finde ich dann die Konstanten/Direktoperanden im 
Assembler listing? Und wie würde z.B. die Instruktion 0x1949 
disassemblieren?

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


Lesenswert?

Christoph K. schrieb:
> PC-relativ: wo finde ich dann die Konstanten/Direktoperanden im
> Assembler listing?

Ist mir jetzt auch nicht klar. Ich habe bislang nur compiler-generierten 
Assemblercode für Cortex-M gesehen, noch nie selbst welchen geschrieben.

Das sieht dann ungefähr so aus:
1
trx_interface_init:
2
        @ args = 0, pretend = 0, frame = 0
3
        @ frame_needed = 0, uses_anonymous_args = 0
4
        ldr     r2, .L9
5
        mov     r1, #65536
6
        mov     r0, #32768
7
        ldr     r3, [r2]
8
        orr     r3, r3, #16
9
        push    {r4, r5, r6, lr}
10
        str     r3, [r2]
11
        mov     r3, #131072
12
        ldr     r4, .L9+4
13
        mov     r2, #16384
14
        mov     r5, #1024
15
        ldr     r6, .L9+8
16
        str     r3, [r4, #48]
17
        str     r3, [r4, #16]
18
        str     r3, [r4]
19
        ldr     r3, .L9+12
20
        str     r1, [r4, #48]
21
        str     r1, [r4, #16]
22
        str     r1, [r4]
23
        str     r2, [r3, #52]
24
        str     r2, [r3, #16]
25
        str     r2, [r3]
26
        ldr     r2, .L9+16
27
        str     r0, [r3, #52]
28
        str     r0, [r3, #16]
29
        str     r0, [r3]
30
        str     r5, [r6, #16]
31
        str     r1, [r2, #20]
32
        str     r1, [r2, #196]
33
        str     r1, [r2, #212]
34
        str     r1, [r2, #176]
35
        str     r1, [r2, #96]
36
        str     r1, [r2, #32]
37
        str     r1, [r2]
38
        str     r0, [r2, #20]
39
        str     r0, [r2, #196]
40
        str     r0, [r2, #212]
41
        str     r0, [r2, #176]
42
        str     r0, [r2, #96]
43
        str     r0, [r2, #32]
44
        str     r0, [r2]
45
        movs    r2, #1
46
        str     r5, [r4, #20]
47
        mov     r0, #1073741824
48
        str     r5, [r4]
49
        mov     r4, #134217728
50
        str     r2, [r3]
51
        movs    r5, #4
52
        str     r2, [r3, #16]
53
        str     r2, [r3, #52]
54
        mov     r2, #536870912
55
        str     r2, [r3, #52]
56
        str     r2, [r3, #16]
57
        str     r2, [r3]
58
        str     r0, [r3, #52]
59
        str     r0, [r3, #16]
60
        str     r0, [r3]
61
        str     r4, [r3, #52]
62
        str     r4, [r3, #16]
63
        str     r4, [r3]
64
        mov     r4, #268435456
65
        str     r4, [r3, #52]
66
        str     r4, [r3, #16]
67
        str     r4, [r3]
68
        ldr     r4, .L9+20
69
        str     r5, [r4, #48]
70
        str     r5, [r4, #16]
71
        str     r1, [r6, #16]
72
        mov     r1, #14336
73
        str     r1, [r3]
74
        str     r1, [r3, #16]
75
        str     r1, [r3, #96]
76
        mov     r1, #6144
77
        str     r1, [r3, #48]
78
        mov     r1, #8192
79
        str     r1, [r3, #48]
80
        str     r0, [r3, #52]
81
        str     r2, [r3, #52]
82
        pop     {r4, r5, r6, pc}
83
.L10:
84
        .align  2
85
.L9:
86
        .word   1074299156
87
        .word   1074663936
88
        .word   1074660864
89
        .word   1074664448
90
        .word   1074662912
91
        .word   1074663424

.L9 ist die besagte Tabelle, im Code bezieht sich der Compiler als 
.L9+<offset> drauf.

Kann sein, dass der Assembler dafür irgendeine eigene Mimik hat.

von Christoph K. (chriskuku)


Lesenswert?

.pool: Tell the assembler where it can safely place data for immediate 
32bit loads (ideally after your return). Use the = prefix operator to 
pool the value. ldr r0, =0x4000002


Es scheint so, als benutzte der Original-Autor

.ltorg für die Konstanten

von Christoph K. (chriskuku)


Lesenswert?

Das, was in Deinem Beispiel unter .L9 zu finden ist, sind aber 
Konstanten aus dem C-Code. Damit wird r0 ja als Basiszeiger 
initialisiert.

Das wäre ja dann keine pc-relative Adressierung.

Interessant wäre mal, den Code 0x1949 zu disassemblieren (nur so als 
Beispiel zum Beispiel ) :)

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


Lesenswert?

Christoph K. schrieb:
> Das wäre ja dann keine pc-relative Adressierung.

Die zugehörigen ldr-Befehle sind meiner Meinung nach am Ende pc-relativ.

Das, was sie darin verwenden, natürlich nicht.

Das mit dem .pool klingt logisch, das "=" ist dann so eine Art Abkürzung 
dafür, dass man nicht laufend im Assembler-Quelltext hin und her 
springen muss zwischen dem Code und der Tabelle.

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


Lesenswert?

Christoph K. schrieb:
> Interessant wäre mal, den Code 0x1949 zu disassemblieren (nur so als
> Beispiel zum Beispiel ) :)

arm-none-eabi-objdump -d

von Hannes J. (pnuebergang)


Lesenswert?

Jörg W. schrieb:
> Das mit dem .pool klingt logisch, das "=" ist dann so eine Art Abkürzung
> dafür, dass man nicht laufend im Assembler-Quelltext hin und her
> springen muss zwischen dem Code und der Tabelle.

Jein, es ist Teil einer Pseudo-Instruktion "LDR Rd,=const" für die der 
Assembler die effizienteste Instruktion einsetzt:

https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/load-immediate-values-using-ldr-rd---const?lang=en

Pools werden im nächsten Abschnitt erklärt:

https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/literal-pools?lang=en

Dann gibt es noch die Pseudo-Instruktion "LDR Rd,=label":
https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/load-addresses-to-a-register-using-ldr-rd---label?lang=en

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


Lesenswert?

Danke, in etwa so hatte ich mir das vorgestellt, aber die Erklärung ist 
natürlich gut.

von Christoph K. (chriskuku)


Lesenswert?

Hannes J. schrieb:
...
> 
https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/load-immediate-values-using-ldr-rd---const?lang=en
>
> Pools werden im nächsten Abschnitt erklärt:
>
> 
https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/literal-pools?lang=en
>
> Dann gibt es noch die Pseudo-Instruktion "LDR Rd,=label":
> 
https://developer.arm.com/documentation/dui0473/m/writing-arm-assembly-language/load-addresses-to-a-register-using-ldr-rd---label?lang=en

Danke für die Links. Da ist es gut erklärt.

Noch eben eine andere Frage: Jörg sagt zwar ich könne ja
1
arm-none-eabi-objdump -d

nehmen.
Aber was ich eigentlich suche, ist ein Assembler-Manual für den 
Cortex-M4 und/oder Arm-Thumb, indem die Instruktionen für einen, der 
einen Assembler schreiben will, erklärt sind. Das Cortex-Manual PM0214 
nennt sich zwar "Programming Manual", aber es fehlen die "Bits". Ich 
will einfach mal eine Instruktion selbst "auseinandernehmen" (oder 
zusammenbauen).

Beitrag #6439131 wurde von einem Moderator gelöscht.
von Hannes J. (pnuebergang)


Lesenswert?

Christoph K. schrieb:
> Aber was ich eigentlich suche, ist ein Assembler-Manual für den
> Cortex-M4 und/oder Arm-Thumb, indem die Instruktionen für einen, der
> einen Assembler schreiben will, erklärt sind.

Wie, du willst dein Leben radikal ändern?

> Das Cortex-Manual PM0214
> nennt sich zwar "Programming Manual", aber es fehlen die "Bits".

Na dann klick dich mal durch:
https://developer.arm.com/architectures/instruction-sets/base-isas/t32

Was du möchtest sind wohl die "Architecture Reference Manuals". Ja, 
Mehrzahl. Alleine für Thumb drei Profiles. Jedes Profile mehrere 
Versionen, zum Teil mit Suplements.  Hier ist z.B. das für ARMv8-M 
https://developer.arm.com/documentation/ddi0553/latest 2000+ Seiten. Die 
für ARMv6 und ARMv7 sind kleiner.

> will einfach mal eine Instruktion selbst "auseinandernehmen".

Wir sehen uns dann in ein, zwei Jahren :)

von Christoph K. (chriskuku)


Lesenswert?

Melde mich schon etwas früher zurück. Danke für die Links.
Konnte das jetzt nachvollziehen und meine Neugier ist erst mal gestillt.
Die 0x1949, die ich mal zerlegen wollte, ist ein (im assembler listing):

15ea 1949  ldr r1,=RCC_AHB1ENR. @entspricht 0x40023830

Das Manual DDI0553B_m_armv8m_arm.pdf sagt auf Seite 647:

C2.4.75   LDR (literal)
  4     9    1    9
|0100|1rrr|immed|iate 8|


Auswertung:

FORTH
ok
hex ok
19 4 * 15ea + . 164e  ok

Schaue ich im gdb das Memory bei 0x164e ab, so steht dort der 
Immediate-Wert
0x40023830

Grüße
Christoph

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.