A list,

CPU The central processing unit (CPU), which contains registers, arithmetic units, and controllers.

  • Register: Stores data
  • Arithmetic machine: Processing data
  • Controller: Control hardwareIOThe high and low level of the port

Common register

  • PC:Program counter to determine instruction position
  • Sp:The address at the top of the stack is stored at any time, and the call function opens up stack space (by operation)Sp registersTo open up stack space)
  • Fp:Also known asx29Registers are general purpose registers that are used at certain times to hold the address at the bottom of the stack
  • X0, x1:A register in which parameters are stored
  • W0, w1:Is the registerX0, x1The low32Bit, in useW0 = x0, w1 = x1

X30 register

  • X30 registerHolds the return address of the currently called function
  • whenretWhen the command executes, it will findX30 registerSave the address value and continue down

Commonly used instructions

  • str: Reads the register value and stores it in memory
  • ldr: Reads a value from memory and stores it in a register
  • stp: Stack instructionstp x0, x1, [sp]Store two values
  • ldp: Unstack instructionldp x0, x1, [sp]Pull out two values
  • bl: puts the address of the next instruction inlr(x30)Register, jump to label to execute instruction
  • ret: DefaultLr (x) registerIs prompted by the underlying instructionCPUThis is the address of the next instruction
  • orr:ORR {condition}{S} Destination register, operand 1, operand 2, and places the result in the destination register

Function parameters and return value under ARM64, function stored in x0~x7 (w0~w7) this 8 register, more than 8 parameters, will be pushed. The return value of the function is placed in the X0 register. 32 general purpose registers.

Second, assembly function nesting

Demo1 – Assembler function nesting

.text
.global _A, B
_A:
    mov x0, #0xaaaa
    bl _B
    mov x0,#0xaaaa
    ret
_B:
    mov x0, #0xbbbb
    ret
Copy the code

Order of execution:

demo`A: 0x102c0a0c4 <+0>: mov x0, #0xaaaa 0x102c0a0c8 <+4>: bl 0x102c0a0d4 ; B ① 0x102C0A0cc <+8>: mov X0, # 0xaAAA ② -> 0x102C0A0D0 <+12>: RETCopy the code

If the command continues, ① and ② will go back and forth. ①->②->①->… . X30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30: x30 .

Here’s how the system handles calls to nested functions:

2, demo2-c function nesting

int A(void);
void b() {
    return;
}
void c() {
    b();
}
int main(int argc, char * argv[]) {
    c();
//    A();
}
Copy the code

Breakpoint step print:

demo`c:
    0x102f9a318 <+0>:  stp    x29, x30, [sp, #-0x10]!
    0x102f9a31c <+4>:  mov    x29, sp
    0x102f9a320 <+8>:  bl     0x102f9a314               ; b at main.m:14:5
    0x102f9a324 <+12>: ldp    x29, x30, [sp], #0x10
->  0x102f9a328 <+16>: ret    
Copy the code
  • STP:Write,X29, x30Write to the stack space
  • stp x29, x30, [sp, #-0x10]! :Is equivalent toSp = sp-0x10 (16 bytes)And assign the address, stretch stack space, stretch stack space size is16Multiples of bytes
  • performC functions
  • LDP X29, X30, [SP], #0x10:Will usespAddress value toX29, x30The assignment,sp+0x10Free up space and keep the stack balanced

Print the value of x30 at each step:

[sp, #-0x10] : [sp, #-0x10] : [sp, #-0x10] : [sp, #-0x10] : The address read by RET is the end address of the current function. If you continue to execute the function, it will exit.

3, demo3- perfect demo1 call the function within the function, save the current function A end address x30 to sp-0x10 (16 bytes), after the end of the function B reset x30 to sp (function A end address), so complete the nested function call.

.text
.global _A, B
_A:
    mov x0, #0xaaaa
    str x30,[sp, #-0x10]!
    bl _B
    mov x0,#0xaaaa
    ldr x30, [sp], #0x10
    ret
_B:
    mov x0, #0xbbbb
    ret
Copy the code

As follows:

Three, functions,

Now that we’ve seen how assembly functions are nested, let’s look at how arguments are handled in the assembly layer.

int sum(int a, int b) { return a+b; } int main(int argc, char * argv[]) {int res = sum(5,7); }Copy the code

Breakpoint to view main function assembly code:

  • sub sp, sp, #0x30:sp-0x30To apply for48Bytes of stack space (spTo the top of the available stack space),subReduction of instruction
  • X29, x30Saves the bottom and top of the stack as the intermediate variable of the nested function
  • You can see the variable values above# # 0 x 5, 0 x7And deposit to theW0, w1In the register

Enter the sum function to see, assembly instruction:

  • insumFunction to stretch the stack space
  • strInstructions will beW0, w1A value in a register is pushed and then taken out for calculation. Why not calculate it directly? This is a compilation rule (compile -> assembly) that prevents the existence of inline functions, which are used within inline functionsW0, w1Register (parameter), which affects the parameter values of the outer function, so the logic is set to facilitate the compiler operation: all parameters must be pushed. Of course, the compiler can also be optimized, and the optimized instructions just goadd sp, sp, #0x10the
  • sp, sp, #0x10: Data processing completes recycling stack space
  • ret: The function with arguments returns the value isX0 registerThe value is notX30 registerThe value of thew0isx0Register low32A, sox0=w0.ret=w0=0x12=12

Compiler optimization: GLEason

Optimized assembly instruction:

  • Optimized out of parameter storage, value, directly add register values
  • No stretch stack space

Lost two hairs!!

Multi-parameter demo

int sum(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j,int k,int l) { return a+b+b+c+d+e+f+g+h+i+j+k+l; } int main(int argc, char * argv[]) {int res = sum(5,7); }Copy the code

The main function assembles the following instructions:

W0 =x0; w9=x9; w0=x0; w9=x9; Before!

Inside the function:

Stretch stack space, store register value, value, add, too many instructions, each instruction takes 1/ main frequency, compound instruction takes 2/ main frequency, so many instructions, too hot.

A local variable

Demo1 – Function with multiple arguments

int funcC() {
    int a = 1;
    int b = 2;
    int c = 3;
    return a+b+c;
}

int main(int argc, char * argv[]) {
    int res = funcC();
}
Copy the code

Function assembly instructions are as follows:

  • Open stack space0x10
  • Store the value toProject.it registerIn (any W)
  • Register values on the stack, off the stack, calculate

Here’s another piece of code:

int funcC() {
    return 1+2+3;
}

int main(int argc, char * argv[]) {
    int res = funcC();
}
Copy the code

Assembly instruction:

Here is carried out an instruction, actually have to do the add related instruction, here has been optimized, but compared with local variables with the above statement, there is no stack up space, save a lot of orders, each instruction takes 1 / frequency, complex instruction takes 2 / frequency, each instruction is discharge time, power consumption, a local variable go easy to use, Of course, in real development, the compiler will optimize away the redundant code.

… …