0

I am trying to run some assembly in C. But I keep getting this error. I am not sure why. I know it is not good practice to mix assembly and C but I am new and would like to convert all of the C to assembly if possible. I don't think I need the attribute but I was trying to do things to remedy this error. The error comes from this line:

__asm("   LDR r1, %[OS_curr] \n"
::"r" (OS_curr)
);

I am running this on a MSP432 microcontroller ARM compiler. Thank you.

void PendSV_Handler() __attribute__((naked));
void PendSV_Handler(void)

{
OSThread *volatile OS_currcopy;
OS_currcopy = OS_curr;
void *sp;
__disable_interrupt();
__asm("   LDR r1, %[OS_curr] \n"
        ::"r" (OS_curr)
   );
if(OS_curr != (OSThread *) 0){
    asm("   PUSH {r4-r11}");
    OS_curr -> sp = sp;
}
sp = OS_next -> sp;
OS_curr = OS_next;

asm("   POP {r4-r11}");
__enable_interrupt();
}

.global         OS_curr
.global         OS_next
.global         PendSV_HandlerAsm

.curradd: .word OS_curr
.currnext: .word OS_next

PendSV_HandlerAsm:
CPSID      i

;if(OS_curr != (OSThread *)0)
LDR        r1, .curradd
LDR        r1, [r0]
CBZ        r1, PendSV_restore

;Push r4  - r11
PUSH {r4-r11}

LDR        r1, .curradd
LDR        r1, [r1]

;OS_curr -> sp = sp;
STR        sp, [r1]

PendSV_restore:

;sp=OS_next -> sp;
LDR        r1, .currnext
LDR        r1, [r0]
LDR        r1, [r0]
STR        sp, [r13]

;OS_curr = OS_next;
LDR        r1, .currnext
LDR        r1, [r1]
LDR        r2, .curradd
LDR        r1, [r1]

;Pop  r4-r11
POP        {r4-r11}

;__enable_interrupts();
CPSIE      i

;return to next thread
BX         r14
Mperez
  • 85
  • 1
  • 6
  • `## Heading ##{`? – klutt Jan 16 '21 at 17:25
  • @klutt likely misclick in SO editor :D – Antti Haapala -- Слава Україні Jan 16 '21 at 17:27
  • Are you sure `__asm` is proper syntax and not `__asm__` as is standard for GCC? or if this is *not* GCC then you cannot use GCC extended assembler... – Antti Haapala -- Слава Україні Jan 16 '21 at 17:29
  • It was the editor my bad. And I am using an ARM Compiler. I am a bit iffy if this is GCC or not. I tried __asm__, __asm, and asm and I get the same error for each one. – Mperez Jan 16 '21 at 17:42
  • 1
    If your question has mistakes, [edit] to fix them. First of all, even if this is GNU C, Extended Asm is not supported in `naked` functions. Also, I think I've seen people say Keil ARMCC doesn't support GNU C extended asm. – Peter Cordes Jan 16 '21 at 17:51
  • @AnttiHaapala: Apparently GCC accepts `__asm()` these days. IDK why; maybe it's helpful to accept `__asm("stuff")` as GNU C basic asm, even though that might have different semantics and requirements than it does in other compilers? Seems more likely to just create problems; you pretty much only ever want Basic Asm in a naked function. But yeah, Keil or other commercial ARM compiler [apparently](https://stackoverflow.com/questions/65460597/inline-assembly-statements-in-c-code-and-extended-asm-for-arm-cortex-architectur/65462892#comment115733758_65460597) doesn't do GNU C Extended inline asm. – Peter Cordes Jan 16 '21 at 17:55
  • So how would I go about fixing this? Is it not possible? – Mperez Jan 16 '21 at 18:10
  • 1
    Write it all in assembly. Or don't use extended assembly there. – KamilCuk Jan 16 '21 at 18:13
  • If I right it in assembly, how do I include the c variable OS_curr? I tried doing .extern OS_curr, extern OS_curr but I get illegal mnemonic specified. Am I doing something wrong? – Mperez Jan 16 '21 at 18:56
  • Assembler can include both code and data. With the Gnu assembler, you can use [`.extern`](https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_7.html#SEC89), but it is not needed as that is the default. The main issue is that global 'C' variables may be adorned with an underscore. In C++ they are mangled; they have a postfix for parameter types. Your handler `_PendSVHandler` can be written is assembler and declared as `extern` in 'C'. You need to conform to the ABI. For ARM, only use registers R0-R3 or else save above R4-R10 (depending). You could refine your question. – artless noise Jan 16 '21 at 19:01
  • How would I go about this? I tried .extern OS_curr at the top of the file and it still says illegal mnemonic specified. I'm not sure what I am doing wrong. I added the assembly file above incase that helps. – Mperez Jan 16 '21 at 19:06
  • If I make the PendSVHandler completely in C, will it be called normally as it is in C? – Mperez Jan 16 '21 at 19:17
  • Your updated assembler looks good. You need to add `.global PendSVHandler` and then you need a prototype for 'C', like `extern void PendSVHandler(void);` so that it is listed in the assembler object as something 'C' can link to. **good** as in it will build an be called. I don't know if it is functionally correct. – artless noise Jan 17 '21 at 15:26
  • I was able to get the assembly running from C. But the issue I am having now is using the global variable in the assembly file. I updated the assembly file above. I know this isn't the best way to get answers but I don't want to have to submit a new question and go through everything again. I thought redeclaring the global variable as another variable would work but that failed. – Mperez Jan 18 '21 at 03:18

0 Answers0