This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem with inline ASM

Other Parts Discussed in Thread: CC430F5135

Hello,

I'm writing a very small program just to test the inline functionality with the CC430F5135 to play around with the program counter:

#define start_add 0x0C08A

and I want to use that macro like this:

asm(" mov %0, PC": "i" (start_add));

but the compiler throws an error: #18 expected a ")"

Any idea on why I'm getting that mistake?

  • Carlos:

    Most of my embedded assembly is  asm(" nop;");

    But you do need a starting and ending " inside of the parenthesis. The ; following the nop is optionional.

    Also, I DO see the space between the first " and the instruction. That is what a lot of people forget...

  • Hi Todd, 

    Actually I have some sentences working in ASM with explicit immediate arguments but I want to have some macros and variables available from C because the program doesn't always get stored in the same location so I need to first extract the location where the PC is pointing and then assigning the one I want.

    Doing that by hand would be a pain and it's not flexible at all... but I really don't get why the ")" expected error occurs, I read the guidelines from TI for inline ASM but they don't seem to work, I even copied some of their examples directly but the same thing happens...

  • inline example: asm("MOV.B &P1IN,&flag");

    Something does not make sense with your asm, are you trying to copy PC to a fixed ram location?
    mov.w PC, &0x0C08A or in your case: mov.w PC,&start_add

    if you are trying to use a macro that change i=0x20 to:  0x020(0x0C08A)
    that is not a valid asm, as only 0x20(R15) is valid

    Or are you trying to change PC? eg a BRANCH

    asm( "BR #start_add+i")

  • Carlos:

    Not exactly sure what you are trying to do, but your asm code

              asm(" mov %0, PC": "i" (start_add));

    should at least have a double-quotes near the semicolon:

             asm(" mov "%0, PC": "i" (start_add)");  //??

    Also not sure if you can nest double-quotes, may need to use single quotes?

  • Another thought:

    Start with a basic mov command, then add as you get clean compiles...

    1. Start with

        asm("  mov  XXX, PC");

     2. Make sure that compiles first, then try to add in your macro capability, a step at a time.

  • The asm statement can contain only one double quoted string, the assembler will copy the string as it is, no possibility to evaluate macro’s or whatever.

    Valid statements in your case are;

    const unsigned int	start_add = 0x0C08A;
    asm ("		.global start_add");
    asm ("		mov.w	#start_add, PC");
    

  • >no possibility to evaluate macro

    But does it allow you to use asm macro's?

    If original poster could explain what exactly what he try do to?

    Wants to jump to a fixed location, based on a i-value array?
    though I see no need for it, if you for some reason have non-relocatable code
    edit the linker for a code:myfixed for reserving a flash segment at the end etc.

     

     

     

     

  • Tony Philipsson said:
    But does it allow you to use asm macro's?

    You can drive a car by just pushing it on the rear, for short distance ok but for longer distances not very safe and comfortable. Why you want to go this way?

    Tony Philipsson said:

    If original poster could explain what exactly what he try do to?

    Wants to jump to a fixed location, based on a i-value array?
    though I see no need for it, if you for some reason have non-relocatable code
    edit the linker for a code:myfixed for reserving a flash segment at the end etc.

    He is just playing around but the asm statement is limited and mend only for these instruction C can’t.

  • Thanks for all your comments, my intention is to branch, right now to the very beginning of the program (the first sentence of the main) but as I was checking the address where the program starts varies according to the code size (I guess).

    I want to make a small function that retrieves that start address (probably by making the get address function to be the first sentence) and then storing it into a global variable to then branch from any section of the code to that first sentence.

    I did it explicitly by looking in the debugger the address of the PC and then writing the immediate data:

    asm(" mov #0x0C08A, PC");

    and it works fine

    Then I wanted to instead of writing the number just use a macro:

    #define start_add 0x0C08A

    And this is where I'm stuck and then the final step would be to use a variable to actually get the address and then use it somewhere else.

    I hope this gives a more clear idea, I'm at the end just playing around to see if this works.

  • Carlos Gonzalez Avelino said:
    a variable to actually get the address and then use it somewhere else

    unsigned int	start_add;
    	asm ("		mov.w	PC, &start_add");
    // or
    	asm ("		mov.w	#start_add, R15");
    	asm ("		mov.w	PC, (R15)");
    

    Carlos Gonzalez Avelino said:
    I'm at the end just playing around to see if this works

    And so you are learning how it works, very good!

  • Carlos, which compiler do you use?

    The syntax you use is for GCC. IAR and CCS require a different syntax for the ASM command (no in/out/clobber information after the ASM text)
    Also, IAR and CCS assembler interpret things differently. One assumes that everything that has no whitespace before is a label, while the other identifies a label by a trailing ‘:’

     Todd, the ‘;’ is the same in assembly as the ‘//’ is in C: a line comment separator.

  • Jens-Michael Gross said:
    Also, IAR and CCS assembler interpret things differently

    Even within CCS (and probably also in IAR) there are different ways depending on assembler for the required processor languish. As I mend CCS is just copying it into the file as it is and then it’s up to the chosen assembler.

  • I'm using CCS, if I write the instructions without any in/out/clobber it works fine as long as they are assembly labels and names, the thing is to "parse" C macros and variables....

  • Leo:
    right. CCS just copies the ASM instructions into its own output without knowing what they do.
    That’s the problem. The compiler cannot optimize across an inline ASM statement, but also doesn’t know which registers the ASM requires or destroys. So any optimization must end before the ASM. All registers need to be saved (if required later) etc.

    GCC uses and requires additional information about what the ASM code does. So it knows which registers are used/altered or untouched. And it can also provide data in a format that is required by the ASM code even though the compiler might have handled the value differently.

    Example: the ASM code uses address instructions on a 32 bit (long) variable to access memory above 64k. But the compiler was holding the long variable in two 16 bit registers. Telling the compiler that the ASM code expects the value in a memory location (so it can do a 20 bit access) will provide working code, while without this information, it is try&error and might break with the next compiler version or C code change.

    Carlos:
    the GCC way also makes it easier to access C or even C++ symbols, as you tell the compiler in the I/O/clobber fields which data your ASM code wants to use. And the compiler inserts the proper symbols into the inline ASM code.
    Macros, however, are always parsed (effectively an advanced text search&replace) before the compiler ever sees the source code.

**Attention** This is a public forum