Analysis on the design method of arm assembly language subroutines

Source: Internet
Author: User

Introduction

In the development of embedded software systemsCLanguage ApplicationProgramDevelopment to improve development efficiency. At the same time, the system often contains some key modules that determine the overall system performance. In order to achieve the best performance, they are often written in assembly language, or in some special circumstances, such as operating hardware, you must also use the assembly language.

Function isCAn important concept in language, which is often used in assembly languages.(Subroutine or procedure)This article uses the glossary to express the same concept. This article first introducesArmThis paper introduces a general method for designing assembly language subroutines, and proposes a new design method based on Stack frames.CLanguage interaction technology.

1 General Method

InArmGenerallyBL (branch and link)Command to call a subroutine,BLThe command first saves the return address in the Link registerR14 (Also knownLr)And jump to the target address. After the sub-routine is executedR14Copy contentPC.

...

BL subr;CallSubr

...;Return here

Subr

...;Child routine body

MoV PC, LR;SlaveSubrReturn

This method is sufficient for leaf routines (that is, routines that do not call other child routines), but it cannot process nested or recursive calls. HypothesisSubrInternal useBLIf another subroutine is calledLRWill be rewritten by the return address of the next call, resulting in an endless loopSubr. To solve this problem,SubrIt must be saved before the second subroutine is called.LR. Furthermore, to enable the subroutine to call another subroutine in any depth, some method must be taken to save any number of return addresses. The most common method is to save the return address in the stack, as shown in the following example:

Subr

Stmfd SP !, {R4-R12, LR};Save all working registers and return addresses, and update the stack pointer.

...;Child routine body

Ldmfd SP! R4-R12, PC};Recover all working registers and load them with the saved return addressPC,

;Update Stack pointer

You can setSubrAny operation registers andLRSave it to the stack and bring them up at the exit point. This allows you to safely call the child routines without worrying about the failure to return the normal data from the child routine due to the rewrite of the return address. Note that the returned address is directly used for loading at the exit point.PCIt is equivalent to the following two commands:

Ldmfd SP! {R4-R12, LR}

MoV PC, LR

2 Stack frame-based child routines

The child routine design method described above can meet the design requirements, but is familiar X86 Programmers in assembly languages are not quite comfortable with it. As we all know, X86 The assembly language subroutine has a standard stack structure, 1 . One of its notable features is EBP Registers are used as reference points to reference parameters and local variables. For example, the first parameter is at the address [EBP + 8]. The advantage of stack frame is that it unifies the programming style of the Assembly subroutine. parameters, return addresses, work registers, or local variables have fixed positions, which not only improvesCodeReadability is also conducive to code maintenance. Based on the above considerations, the stack frame concept is introduced Arm The following example shows the design of the assembly language subroutine. For simplicity, assume that Subr The prototype is Int subr (int A, int B, int C, int D, int e, int F ); Obviously, according APCs (ARM Procedure Call Standard ) , Parameter A-d Register R0-R3 And the remaining two parameters are passed. E And F Pass through the stack. Final stack frame structure 2As shown in the following figure: 1 In X86 The only difference between the frame structure and the local variable is the opposite location of the working register. The reason for this difference is to make full use Arm Multi-register Load-store Command advantages.

Caller

...;Parameter omittedA-dTransfer code

MoV R4, #2

STR R4, [Sp, #-4]!; 1)Set the parameter FPush to stack

MoV R4, #1

STR R4, [Sp, #-4]!;Set parametersEPush to stack

BLSubr; 2)Call a subroutineSubr

Add SP, SP, #8; 8)Balance the stack.SubrThe returned value is saved inR0Medium

 

Subr

StmfdSP !, {R4-R7, FP, LR}; 3)Save the working register,FpAndLR

Add FP, SP, #16; 4)Calculate frame pointer

SubSP, SP, #8; 5)Allocate space for local variables

LDR R4, [FP, #8];Load parametersE

LDR R5, [FP, #12];Load parametersF

...; SubrChild routine body

AddSP, SP, #8; 6)Release local variable space

Ldmfd SP !, {R4-R7, FP, PC}; 7)Recover registers and return

Figure1x86Stack frame structure

Figure2 armStack frame structure in

The following details how to build a stack frame step by step. The sequence number corresponds to the sequence number in the sample code comment:

1)GenerallyStr rn, [Sp, #-4]!The command pushes the parameters required by the subroutine into the stack. Note thatAPCsFirst, consider using registersR0-R3PASS Parameters. The remaining parameters are pushed to the stack in reverse order. If you use a registerR0-R3All parameters can be passed, so this step can be omitted.

2)BLThe command pushes the return address to the stack and jumps to the specified subroutine to continue execution. Since then, all stack modification work has been transferred to the child routine.

3)If the subroutine needs to useR4-R11Working registers, which must be pushed into the stack, and the old frame pointer registersFpAnd link registerLRPush into the stack, which can be efficiently completed in a single instruction.

4)Adjust frame pointerFpTo reference stack parameters and variables. In this example, you can useLDR r0, [FP, #8]Reference parametersE,LDR r0, [FP, #-20]Reference the first local variable.

5)Allocate8The local variables of the sub-routine. However, if you do not need to use local variables, skip this step. AndCISCArchitectureX86Different processors,ProteusArchitectureArmThe processor has a large number of General registers, suchR0-R7,LRSo in most cases, you do not need to allocate stack space for local variables.

6)If you previously allocated stack space for local variables, you need to release them to maintain a stack balance.

7)Recover the registers stored in the stack in step 3.PCRegisters are returned from the subroutine.

8)SubroutineSubrReturn here after the execution is complete. This step is very important becauseCallerBefore callingSubrParametersEAndFPushed Into the stack, so fromSubrAfter ReturnCallerThe two parameters must pop up the stack to maintain the balance of the stack. Of courseCThe compiler is responsible for completing the stack balancing when a subroutine is called in a language.

3 Assembly Language and C Language Interaction

After compiling the Assembly subroutine, the next question is howCLanguage. Essentially, no matter which language is used for code writing, the routines that call other modules in each other must follow a common parameter and result transfer convention. ForArmThis Convention is calledArmThe process call standard, which defines:

LUsage of General registers

LType of stack used

LTransmission of parameters and results

LArmShared Library Mechanism support

Because the code generated by the compiler always strictly followsAPCsTherefore, you only need to ensure that the compiled Assembly Code conformsAPCsYou can. The following example shows howCThe language calls the child routines written in assembly language to implement the memory copy function. The development environment isRealview mdk3.22a.

;Define and exportMymemcpyOfMymemcpy. sFile

; R0Destination Address,R1Point to source address,R2Copy Length

Area demo, code, readonly

Export mymemcpy

Mymemcpy

Stmfd SP !, {R4, LR}

MoV R3, R0;Retrieve Destination Address

MoV R12, R1;Retrieve Source Address

Copy

CMP R2, #0;If the length is less than or equal0Exit

Ble exit

Sub R2, R2, #0x1

Beq exit

Ldrb LR, [R12], #0x1

Strb LR, [R3], #0x1

B copy

Exit

Ldmfd R13 !, {R4, PC}

End

// Main. cTest procedure

Extern void * mymemcpy (void * DST, const void * SRC, size_t size );

Int main (INT argc, char ** argv)

{

Const char * src = "first string-source ";

Char DST [] = "second string-destination ";

Mymemcpy (DST, SRC, strlen (SRC) + 1 );

Return (0 );

}

Call from assembly languageCThe key of a function is howCThe prototype of the function correctly transmits parameters. The following example shows how to callCLibrary functionsStrcmpThe prototype isInt strcmp (const char * S1, const char * S2 );, It only has two pointer type parameters, soR0AndR1Point to the first and second strings respectively. Note thatCLibrary Function, select the project option dialog box,TargetTabUse microlib.

Area |. Text |, code, readonly

Export main;ExportMain

Import _ main

Import strcmp;ImportStrcmpFunction

Main

Stmfd SP !, {R4, LR };SaveLR

ADR r0, big;PassR0PASS Parameters1

ADR R1, small;PassR1PASS Parameters2

BL strcmp;CallStrcmpLibrary functions

Ldmfd SP !, {R4, PC}

Big

 DCB "big", 0

Small

DCB "small", 0

End

Summary

This article starts from the author's practice and talks aboutArmDesign method of assembly subroutine and itsCYour experience in language interaction should be corrected.

References

1.Andrew N. sloss, Dominic Symes, Chris WrightBy.Translated by Shen Jianhua. ArmEmbedded System Development-Software Design and Optimization.Beijing University of Aeronautics and Astronautics Press.

2.David seal. Arm Architecture Reference Manual, second edition, Addison-Wesley.

3.RealviewCompilation tool2.0Version-Developer Guide, Arm Limited.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.