Mixed programming of C and assembly in ARM and examples Mixed programming of C and assembly in ARM and examples

Publisher:MengyunLatest update time:2016-07-06 Source: eefocusKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
In embedded system development, the main programming languages ​​currently used are C and assembly. C++ has a corresponding compiler, but it is still rarely used. In slightly larger-scale embedded software, such as OS, most of the code is written in C, mainly because C has a better structure, is easy for people to understand, and has a large number of support libraries.

    Despite this, assembly language is still used in many places, such as the initialization of the hardware system when starting up, including the setting of the CPU status, enabling of interrupts, setting of the main frequency, and the control parameters and initialization of RAM. Some interrupt handling may also involve assembly language. Another place where assembly language is used is in some code blocks that are very sensitive to performance. This cannot rely on the code generated by the C compiler, but requires manual compilation of assembly language to achieve the purpose of optimization. Moreover, assembly language is closely linked to the CPU instruction set. As a low-level embedded system development, proficiency in the use of corresponding assembly language is also necessary.

    For pure C or assembly programming, please refer to relevant books or manuals. Here we mainly discuss mixed programming of C and assembly, including function calls between them. The following is a discussion of four cases, not involving C++ for the time being.

      1. Embed assembly in C language

       The assembly instructions embedded in C include most ARM and Thumb instructions, but their use is somewhat different from the instructions in the assembly file and there are some limitations, mainly in the following aspects:

       a. You cannot assign values ​​directly to the PC register. Program jumps must use the B or BL instruction.

       b. When using physical registers, do not use overly complex C expressions to avoid physical register conflicts

       c. R12 and R13 may be used by the compiler to store intermediate compilation results. When calculating expression values, R0 to R3, R12 and R14 may be used for subroutine calls. Therefore, avoid using these physical registers directly.

       d. Generally, do not specify physical registers directly, but let the compiler allocate them.

       The mark used for inline assembly is __asm ​​or asm keyword, and its usage is as follows:

__asm

{

instruction [; instruction]

[instruction]

}

asm(“instruction [; instruction]”);

       The following example shows how to embed assembly language in C.

#include

void my_strcpy(const char *src, char *dest)

{

char ch;

__asm

{

loop:

ldrb ch, [src], #1

strb ch, [dest], #1

cmp ch, #0

bne loop

}

}

int main()

{

char *a = "forget it and move on!";

char b[64];

my_strcpy(a, b);

printf("original: %s", a);

printf("copyed: %s", b);

return 0;

}

  Here, the value transfer between C and assembly is implemented using C pointers. Since pointers correspond to addresses, they can also be accessed in assembly.

       2. Use C-defined global variables in assembly

     Inline assembly does not require editing assembly language files separately, which is relatively simple, but has many limitations. When there are many assembly codes, they are generally placed in separate assembly files. At this time, some data needs to be transferred between assembly and C. The easiest way is to use global variables.

 

#include

int gVar_1 = 12;

extern asmDouble(void);

int main()

{

printf("original value of gVar_1 is: %d", gVar_1);

asmDouble();

printf(" modified value of gVar_1 is: %d", gVar_1);

return 0;

}

       The corresponding assembly language file

;called by main(in C),to double an integer, a global var defined in C is used.

AREA asmfile, CODE, READONLY

EXPORT asmDouble

IMPORT gVar_1

asmDouble

ldr r0,=gVar_1

ldr r1, [r0]

move r2, #2

mul r3, r1, r2

str r3, [r0]

mov pc, lr

END

       3. Calling assembly functions in C

     To call a function in an assembly file in C, there are two main tasks to do. First, declare the function prototype in C and add the extern keyword. Second, export the function name in assembly using EXPORT and use the function name as the identifier of the assembly code segment. Finally, return with mov pc, lr. Then, you can use the function in C. From the perspective of C, it is not known whether the function is implemented in C or assembly. The deeper reason is that the function name in C indicates the starting address of the function code, which is consistent with the label of the assembly.

 

#include

extern void asm_strcpy(const char *src, char *dest);

int main()

{

const char *s = "seasons in the sun";

char d[32];

asm_strcpy(s, d);

printf("source: %s", s);

printf(" destination: %s",d);

return 0;

}

;asm function implementation

AREA asmfile, CODE, READONLY

EXPORT asm_strcpy

asm_strcpy

loop

ldrb r4, [r0], #1 ;address increment after read

cmp r4, #0

frog over

strb r4, [r1], #1

b loop

over

mov pc, lr

END

  Here, the parameter passing between C and assembly is carried out according to the provisions of ATPCS (ARM Thumb Procedure Call Standard). Simply put, if a function has no more than four parameters, they are passed using R0-R3. If there are more than four, the stack is used, and the return value of the function is returned through R0.

       4. Calling C functions in assembly

     To call a C function in assembly, you need to IMPORT the corresponding C function name in the assembly, and then put the C code in a separate C file for compilation. The rest of the work is handled by the connector.

;the details of parameters transfer comes from ATPCS

;if there are more than 4 args, stack will be used

EXPORT asmfile

AREA asmfile, CODE, READONLY

IMPORT cFun

ENTRY

mov r0, #11

mov r1, #22

rice r2, #33

BL cFun

END

 

int cFun(int a, int b, int c)

{

return a + b + c;

}

  When calling a C function in assembly, the parameter passing is also implemented through ATPCS. It should be pointed out that when the number of function parameters is greater than 4, the stack must be used. For details, see the ATPCS specification.

       summary

  The above examples demonstrate some common C and assembly mixed programming methods and basic ideas in embedded development. In fact, the core issue is how to pass values ​​between C and assembly. The rest is to handle them in their own way. The above is just a starting point. For more detailed and complex usage methods, you need to combine actual applications and refer to relevant materials.

illustrate

  The above code is compiled in the ADS 1.2 project and passed the software simulation in the corresponding AXD.

When programming in C and assembly, there are interface issues between variables and functions in C and assembly.
Variables defined in a C program are put into the .bss area after being compiled into an .asm file, and the variable names are preceded by an underscore. Functions defined in a C program are also preceded by an underscore after being compiled. For example:

extern int num becomes .bss _num, 1
extern float nums[5] becomes .bss _nums, 5
extern void func ( ) becomes _func,  The mutual calls between assembly and C can be divided into the following situations: (1) Accessing variables and functions in a C program in an assembly program.

In  an assembly program, you can use _XX to access variable XX in C. When accessing an array, you can use _XX+offset to access it, such as _XX+3 to access XX[3] in the array.  When calling a C function in an assembly program, if no parameters are passed, you can directly use _funcname. If there are parameters to be passed, the leftmost parameter in the function is given by register A, and the other parameters are given in order from the stack. The return value is returned to register A or the address given by register A. Also note that in order for assembly language to access variables and functions defined in C language, they must be declared as external variables, that is, with the extern prefix. (2) Accessing variables in the assembly program in the C program If you need to access variables in the assembly program in the C program, the variable name in the assembly program must start with an underscore and use global to make it a global variable. If you need to call a procedure in the assembly program in the C program, the procedure name must start with an underscore, and the procedure must be correctly written according to the mode used when the C program is compiled, whether it is the stack-based model or the register argument model, so that it can correctly obtain the calling parameters. (3) Online assembly Directly insert asm("  ***  ") into the C program   , embed assembly statements. It should be noted that this usage should be used with caution. Online assembly provides the ability to directly read and write hardware, such as reading and writing interrupt control enable registers, but the compiler does not check and analyze online assembly language. Inserting online assembly language to change the assembly environment or possibly change the value of C variables may cause serious errors. 2. Changes in addressing methods in assembly and C interfaces: It should be noted that in C language, the creation and access of local variables are implemented through the stack, and its addressing is implemented through the stack register SP. In assembly language, in order to make the program code more concise, in the direct addressing mode, the lower 7 bits of the address are directly included in the instruction. The specific location that these lower 7 bits can address can be determined by the DP register or the SP register. The specific implementation can be achieved by setting the CPL bit of the ST1 register. CPL=0, DP addressing, CPL=1, SP addressing. When DP addressing is used, DP provides the high 9-bit address, which together with the low 7 bits form a 16-bit address; when SP addressing is used, the 16-bit address is obtained by directly adding SP (16 bits) and the low 7 bits. Since in the C language environment, the addressing of local variables must be implemented through the SP register, in mixed programming, in order to prevent the assembly language from affecting the stack register SP, the usual way is to use DP addressing in the assembly environment, so that the two do not interfere with each other. In programming, just pay attention to the correct setting of the CPL bit.  




    









  





Keywords:ARM Reference address:Mixed programming of C and assembly in ARM and examples Mixed programming of C and assembly in ARM and examples

Previous article:Porting MySQL to Embedded ARM Platform
Next article:ARM Assembly Example - Button LED (Loop)

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号