Forum: Compiler & IDEs Alternative zu Assembler


von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Hallo,
ich schreibe gerade für meine BLE Debug Probe einige Flash Routinen für 
verschiedene Microcontroller.

Diese Routinen werden ins RAM des Targets geladen und dort ausgeführt, 
um das flash der Controller zu beschreiben. Ausgeführt werden diese 
Routinen, in dem die Parameter direkt in Register geladen werden, der PC 
auf den Start der Routine gesetzt wird und die CPU nach einen Halt 
wieder los gelassen wird. Am Ende der rennt die Routine auf einen 
Break-Point und der Debugger wartet auf das Erreichen des Breakpoints. 
Dann kann sich der Debugger das Ergebnis der  Routine in einem Register 
abholen (so grob skizziert).

Im Moment geht es ausschließlich um ARM Assembler (Thumb). Einige Flash 
Controller sind allerdings komplex genug, damit es recht schnell 
unübersichtlich wird, diese Routinen von Hand in Assembler zu schreiben.

Welche Alternativen hätte ich? (Einen Stack könnte ich wohl in der Regel 
aufsetzen). Verwendete Toolchain ist arm-none-eabi-gcc.

schöne Grüße,

Torsten

von Dr. Sommer (Gast)


Lesenswert?

Seltsame Frage...

Torsten R. schrieb:
> Verwendete Toolchain ist arm-none-eabi-gcc.

Das unterstützt C, C++ und Assembler. Die sollten alle drei gehen. Wo 
ist das Problem?

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Dr. Sommer schrieb:
> Seltsame Frage...
>
> Torsten R. schrieb:
>> Verwendete Toolchain ist arm-none-eabi-gcc.
>
> Das unterstützt C, C++ und Assembler. Die sollten alle drei gehen. Wo
> ist das Problem?

Ich kann in C, C++ keinen ausführbaren Code deklarieren, der ausserhalb 
einer Funktion steht:
1
start:
2
    MOV R7, #result_ok
3
    LDR R3, nvmc_ready                  /* R3 == NVMC_READY                         */
4
    LDR R4, nvmc_config                 /* R4 == NVMC_CONFIG                        */
5
6
    MOV R5, #NVMC_CONFIG_WEN_Wen
7
    STR R5, [ R4 ]                      /* NVMC_CONFIG = NVMC_CONFIG_WEN_Wen        */
8
...
9
    BKPT

Aufgerufen wird so eine "Routine", in dem ich die CPU des Controllers 
anhalte, die Routine ins RAM lade. Den PC auf den Anfang der Routine 
setze, die Register mit Parametern fülle und die CPU dann wieder weiter 
laufen lasse.

Am Ende der Routine ist dann ein SW-Breakpoint, auf den wartet der 
Debugger.

Ich könnte natürlich von dieser ASM-Routine aus, eine C Funktion 
aufrufen. Ich frage mich, ob es aber ggf. einfacher geht, ohne direkt 
Assembler schreiben zu müssen.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Ich habe gerade mal in die Source von der Blackmagic Probe geguckt. Die 
verwenden C Funktionen, der mit `__attribute__((naked))` anotiert ist:
1
void __attribute__((naked))
2
efm32_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size, uint32_t msc)
3
{
4
  ...
5
}

Die Dokumentation vom GCC sagt dazu aber:
1
naked
2
This attribute allows the compiler to construct the requisite function declaration, while allowing the body of the function to be assembly code. The specified function will not have prologue/epilogue sequences generated by the compiler. Only basic asm statements can safely be included in naked functions (see Basic Asm). While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported.

von Vincent H. (vinci)


Lesenswert?

Das Problem ist dass es keinerlei Garantie gibt dass Code innerhalb 
einer Funktion nicht munter am Stack herumspielt. Das Attribut entfernt 
lediglich Stackpointer Manipulation am Anfang und Ende einer Funktion, 
nicht aber dazwischen.

von Bernd K. (prof7bit)


Lesenswert?

Dann mach halt normale C-Funktionen, auf die paar Byte wirds ja wohl 
nicht ankommen. Initialisier den Stackpointer, ruf die Funktion auf und 
wenn sie zurückkommt lass es in den Breakpoint laufen. Dann hast Du ne 
kleine Hand voll Assembler der immer gleich ist und eine bliebig 
komplexe stinknormale C-Funktion.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Vincent H. schrieb:
> Das Problem ist dass es keinerlei Garantie gibt dass Code innerhalb
> einer Funktion nicht munter am Stack herumspielt. Das Attribut entfernt
> lediglich Stackpointer Manipulation am Anfang und Ende einer Funktion,
> nicht aber dazwischen.

Genau, und ich würde den Compiler gerne dazu bringen, z.B. eine 
Fehlermeldung auszugeben, wenn er doch einen Stackframe braucht (z.B. 
weil die Register nicht ausreichen).

von Christopher J. (christopher_j23)


Lesenswert?

Torsten R. schrieb:
> Vincent H. schrieb:
>> Das Problem ist dass es keinerlei Garantie gibt dass Code innerhalb
>> einer Funktion nicht munter am Stack herumspielt. Das Attribut entfernt
>> lediglich Stackpointer Manipulation am Anfang und Ende einer Funktion,
>> nicht aber dazwischen.
>
> Genau, und ich würde den Compiler gerne dazu bringen, z.B. eine
> Fehlermeldung auszugeben, wenn er doch einen Stackframe braucht (z.B.
> weil die Register nicht ausreichen).

Beim GCC kann man sich mit -fstack-usage den Stackbedarf der einzelnen 
Funktionen ausgeben lassen. Das landet dann in einer .su-Datei die du 
mit einem Python-Script o.Ä., aufgerufen durch dein Build-System 
auswerten könntest.

Eine direkte Warnung kannst du ausgeben, wenn du die Compileroption 
-Wstack-usage=byte-size nutzt, wobei byte-size in deinem Fall dann 
logischerweise 0 sein müsste.

von Mike (Gast)


Lesenswert?

>Welche Alternativen hätte ich? (Einen Stack könnte ich wohl in der Regel
>aufsetzen). Verwendete Toolchain ist arm-none-eabi-gcc.

Nimm C, das ist nichts anderes als ein Makro-Assembler!

von J. V. (janvi)


Lesenswert?

da gibt es ja noch das Schlüsselwort Register wo man den Compiler fast 
soweit kriegt daß er Code absetzt wie man ihn auch selbst geschrieben 
hätte. Nur für einen Schleifenaufbau mit Rotieren durchs Carry bit habe 
ich noch nichts gefunden. Aber man muß halt immer höllisch aufpassen daß 
gcc keinen Blödsinn macht. Ist halt wie beim Autorouter in der 
Hardware...

von Oliver S. (oliverso)


Lesenswert?

J. V. schrieb:
> da gibt es ja noch das Schlüsselwort Register

welches seit einem gefühlten Jahrhundert ganz offiziell von jedem 
Compiler ignoriert wird.

Oliver

von leo (Gast)


Lesenswert?

Oliver S. schrieb:
> J. V. schrieb:
>> da gibt es ja noch das Schlüsselwort Register
>
> welches seit einem gefühlten Jahrhundert ganz offiziell von jedem
> Compiler ignoriert wird.

Oder besser nach eigenem Gutduenken optimiert...
Deshalb sagte ich dem gcc sowas:
1
register int foo asm ("r12");

> Oliver

leo

von J. V. (janvi)


Lesenswert?

Die gesamten Mikrokontroller sind von GCC Code besetzt. Die gesamten? 
Nein, ein von unbeugsamen Programmieren erstellter Compiler macht das 
anders (cosmic)

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