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.

How to call assembly code from C in Linux?

Hi,

I am using Linaro Toolchain on Sitara SDK, Ubuntu 12.04, 32 bit. I would like to write C code and the C calls some assembly function. For below simple code snippet, it generates strange behavor.

    .align 4   //2        // Align the function code to a 4-byte (2^n) word boundary.
    .arm            // Use ARM instructions instead of Thumb.
//    .globl _$0        // Make the function globally accessible.
//    .no_dead_strip _$0    // Stop the optimizer from ignoring this function!
//    .private_extern _$0
    .globl _start
_start:
    mov r0, #2 /* Put a 2 inside the register r0 */
    bx lr      /* Return from main */
   

extern int _start(void);

int main(void) {
    printf("Hello World!\n");
    _start();
    printf("Hello Sitara World!\n");
    
    return 0;
}

The above code prints "Hello World" continuously in the terminal. Even I comment out two asm lines: mov r0,#2 and bx lr

The only way to stop continuous "Hello World" is that I comment out _start in the main() function.

Could you tell me how to make C calls asm function?

Thanks,

  • Instead of _start, can you rename your routine to something else? I just wrote and compiled a hello world application and disassembled it. It looks like the C runtime library already has a start function. This is from the disassembly without your _start routine:

    Disassembly of section .text:

    000082f4 <_start>:
        82f4:       f04f 0b00       mov.w   fp, #0
        82f8:       f04f 0e00       mov.w   lr, #0
        82fc:       f85d 1b04       ldr.w   r1, [sp], #4

    Maybe rename yours from _start to _sitara.

    Steve K.

  • Thanks for the prompt answer. It has a new error now. The compiler complains that sitara():

    Description    Resource    Path    Location    Type
    undefined reference to `sitara'    GNU_hello1.c    /GNU_hello1    line 10    C/C++ Problem

    Below is the main(). What is wrong?

    extern int sitara(void);

    int main(void) {
        printf("Hello World!\n");
        sitara();
        printf("Hello Sitara World!\n");
        
        return 0;
    }

  • Excuse me. I should attach the compiler and linker commands in last post.

    09:22:53 **** Incremental Build of configuration Debug for project GNU_hello1 ****
    make all
    Building file: ../GNU_hello1.c
    Invoking: Cross GCC Compiler
    arm-linux-gnueabihf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"GNU_hello1.d" -MT"GNU_hello1.d" -o "GNU_hello1.o" "../GNU_hello1.c"
    Finished building: ../GNU_hello1.c
     
    Building target: GNU_hello1
    Invoking: Cross GCC Linker
    arm-linux-gnueabihf-gcc  -o "GNU_hello1"  ./GNU_hello1.o   
    ./GNU_hello1.o: In function `main':
    /home/robert/workspace_v5_5/GNU_hello1/Debug/../GNU_hello1.c:10: undefined reference to `sitara'
    collect2: error: ld returned 1 exit status
    make: *** [GNU_hello1] Error 1

    09:22:53 Build Finished (took 215ms)

    In fact, I have noticed the problem from the above commands. It does not compile asm function sitara(). I am further puzzled about how to set it in makefile, or CCS v5.5.0? It is quite different from C6000 under CCS. Could you explain and help me?

    Thanks again.

  • Hi,

    After I manage to set the file build settings, it compiles successfully. The new problem is that it complains

    Segmentation fault

    even there is a nop like command.

        .align 4   //2        // Align the function code to a 4-byte (2^n) word boundary.
        .arm            // Use ARM instructions instead of Thumb.
        .globl sitara
    sitara:
      mov r0,r0

    What is wrong?

    Thanks

  • Bear with me, I'm a command line guy, not CCS. Below is my simple C program, hello.c, that I compiled with arm-linux-gnueabihf-gcc -c hello.c just to look at the resultant object code

      1 #include <stdio.h>
      2
      3 extern int sitara();
      4
      5 main()
      6 {
      7    int rc;
      8
      9    printf("Hello World!\n");
     10    rc = sitara();
     11    printf("rc=%d from sitara()\n", rc);
     12 }

    If I disassemble with arm-linux-gnueabihf-objdump -D hello.o I see

      5 Disassembly of section .text:
      6
      7 00000000 <main>:
      8    0:   b580            push    {r7, lr}
      9    2:   b082            sub     sp, #8
     10    4:   af00            add     r7, sp, #0
     11    6:   f240 0000       movw    r0, #0
     12    a:   f2c0 0000       movt    r0, #0
     13    e:   f7ff fffe       bl      0 <puts>
     14   12:   f7ff fffe       bl      0 <sitara>
     15   16:   6078            str     r0, [r7, #4]
     16   18:   f240 0000       movw    r0, #0
     17   1c:   f2c0 0000       movt    r0, #0

    Notice the half-word boundaries. This suggests to me that the main() code runs in thumb mode. So I changed the .arm to .thumb in my simple sitara.S file and I can build the code and it runs without the segfault. Below is my sitara.S file

      1
      2         .thumb
      3         .text
      4
      5         .globl  sitara
      6  sitara:
      7         mov     r0, #2
      8         mov     pc, lr

    I built with arm-linux-gnueabihf-gcc -o hello hello.c sitara.S

    Steve K.