This is the fifth day of my participation in Gwen Challenge

IOS basic principles + reverse article summary

This article mainly explains compiler optimization and pointer assembly

Compiler optimization

Set up the

Available in the projectBuildSetting->Optimization LevelFound in the general optimization scheme selectionFS(Fastest, Smallest)

Case analysis

There is the following code

int main(int argc, char * argv[]) {
    
    int a = 1;
    int b = 2;
}
Copy the code
  • The assembly without optimization is as follows

  • Will optimize the program fromNonetoFS, compiled as follows

Modification 1: called in main

int sum(int a, int b){
    return a + b;
}


int main(int argc, char * argv[]) {
    
    sum(1, 2);
}
Copy the code

Check whether there is 1,2 at this time, and find that there is no assembly code related to sum. The optimization principle is as follows: removing sum has no impact on the result of program operationPrinciple 1: Code that has no effect on the result will be optimized by the compiler.

Modification 2: Print the result of sum

int sum(int a, int b){
    return a + b;
}


int main(int argc, char * argv[]) {
    int a = sum(1, 2);
    printf(@"%d", a);
}
Copy the code

At this point, if sum is optimized, the execution result will be affected. You can see that the sum function has been optimized away,Optimization becomes a result

Pointer to the

In OC, either arguments or return values, if objects are passed/returned, these objects are Pointers. Let’s look at disassembly of Pointers

void func(){ int *a; printf("%lu", sizeof(a)); } int main(int argc, char * argv[]) {func(); }Copy the code

Analyze the assembly code of the above code

Pointer to the common sense

Pointer increment and decrement operations

void func(){ int *a; a = (int *)100; a++; printf("%d", a); } <! -- Print result --> 104Copy the code
  • Question: After a++, what is a?

    • It’s 104 becauseThe incrementation and decrement of a pointer depend on the width of the data type to which it pointsThat is, because a points to the dataintThe width of int is 4 bytes
  • Change 1: What is the result if int is changed to char?

    • Because a points to the datacharChar is 1 byte wide
void func(){ char *a; a = (char *)100; a++; printf("%d", a); } <! -- Print results --> 101Copy the code
  • Modification 2: What if int is changed to int*?
    • Because a points to the dataint*Is a pointer, and the width of the pointer is 8 bytes
void func(){ int **a; a = (int **)100; a++; Printf ("%d", a); printf("%d", a); } <! Print the result --> 108Copy the code
  • Change 3: What if I changed a++ to a = a+ 1?
    • Increment and decrement is related to the compiler!
    • Note: the +1 is adding a step, while the step of a is (int*), which is 8 bytes
void func(){ int **a; a = (int **)100; // a++; A = a + 1; a = a + 1; printf("%d", a); } <! Print the result --> 108Copy the code

Pointers and Pointers evaluate

What is the result of subtracting two Pointers?

void func(){ int *a; a = (int *)100; int *b; b = (int *)200; int x = a - b; printf("%d", x); } <! -- Print the result --> -25Copy the code
  • Because the width of (100-200) /int = -100/4 = -25

  • Note: The unit of operation for Pointers is the width of the data type executed

  • Question: Can Pointers be if-else size ratios?

    • Yes, we know that types can be converted to each other, but constructs and primitive types cannot be converted to each other
    • Any type can be used& (take address symbol)The values
void func(){ int *a; a = (int *)100; int *b; b = (int *)200; if (a > b) { printf("a > b"); }else{ printf("a <= b"); }} <! -- Print result --> a <= bCopy the code

Disassembly of Pointers

Define a pointer, assign a value, and view its assembly code

void func(){
    int *a;
    int b = 10;
    a = &b;
}
Copy the code

Below is a compilation and analysis of the code run

Pointer to an array

Question 1: Can I get an array out of an array correctly by using the following method?

void func(){ int arr[5] = {1, 2, 3, 4, 5}; for (int i = 0; i < 5 ; i++) { // printf("%d", arr[i]); printf("%d",*(arr + i)); // we can't use arr++ because the compiler doesn't allow}}Copy the code

It is possible to run discovery, so there are the following equivalents:

  • Reciprocal relationship:int *a == arr[0] == arr

Question 2: Is a++ ok in the for loop if arr is assigned to pointer A?

void func(){ int arr[5] = {1, 2, 3, 4, 5}; int *a = arr; for (int i = 0; i < 5 ; i++) { // printf("%d", arr[i]); printf("%d",*(a++)); }}Copy the code

It is also possible to run discovery

Basic usage of Pointers

  • Define a pointer and take the value from the pointer
void func(){ char *p1; char c = *p1; // select * from p1;Copy the code

The cause is 0 as the address value. The following is the assembly analysis

* What if I rewrite it as p1 plus 0?

void func(){ char *p1; char c = *p1; Char d = *(p1+0); }Copy the code

View assembly code:

  • p1Pointer toSp +0x8 value in the stack area, which is equivalent toP1 - > 0 x0 (by 8)
  • cThat’s the same thing as taking the value of X8, which is equal to[X8]
  • dAgain, I’m going to take the value of X8, which is equal to[X8]

* What if I change it to p1 plus 1?

void func(){ char *p1; char c = *p1; Char d = *(p1+1); }Copy the code

View the assembly:

  • p1Pointer toSp +0x8 value in the stack area, which is equivalent toP1 - > 0 x0 (by 8)
  • cThat’s the same thing as taking the value of X8, which is equal to[X8]
  • dAgain, I’m going to take the value of X8, which is equal to[X8+0x1]

What if I changed a char to an int?

void func(){ int *p1; int c = *p1; Int d = *(p1+1); }Copy the code

The following is a compilation of func functions, where d is taken[x8+0x4]The value of the address, because int is 4 bytes,0x4isInt Step size

What if I changed an int to an int? *

void func(){ int **p1; int *c = *p1; Int *d = *(p1+1); }Copy the code
  • View the assembly at this timedIs to take[x8+0x8]The value of the address, because int* is a pointer, eight bytes long,0x8isStep size of type int*

  • How many bytes does int** need to be stretched?

The actual need is 3×8=24 bytes, since assembly is 16-byte alignment, sub minus 0x20 is required

  • I’m going to add one moreint* p2How many bytes does stack space stretch?

The discovery is still 0x20

  • Let’s add one morechar c1?

We’re over 32, so we need to stretch 16 more bytes

Multilevel pointer

1. Secondary Pointers

There is the following code

void func(){
    int **p1;
    int c = **p1;
}
Copy the code

Run the crash to see its compilation

  • X8 takes the value of *p1 (the address of the first-level pointer)

  • W9 takes the value of **p1 (the address of the second-level pointer)

2. Multi-level pointer addition operation

void func(){ char **p1; // char c = p1+2; Char c = *(*(p1 +2) +2); // The outermost layer of the +2, is added 0x2 (execute data type is char)}Copy the code
  • At this point, the +2 in C is +0x10 (execution data type is char*)

  • At this point, the outermost +2 in D is plus 0x2.

What about the following form?

void func(){ char **p1; // char c = p1+2; Char c = *(*(p1 +2) +2); Char c2 = p1[1][2]; // equivalent to the above}Copy the code
  • P1 [1] where 1 represents 0x8 (type char*)

  • P1 [1][2] where 2 represents 0x2 (type char)

From the results of the assemblyp1[1][2]with*(*(p1 + 2) + 2)Are equivalent

conclusion

  • Compiler optimization:

    • 1, set: BuildSetting->Optimization Level

    • 2. Principle of optimization: code that has no effect on the result is optimized by the compiler

    • 3. Compiler optimization, which is essentially the optimization process of LLVM, actually optimizes assembly code (can be understood as assembly instructions will be reduced)

  • Pointer:

    • 1. The increment and decrement of a pointer depends on the width of the data type to which the pointer is pointing. The operation is based on the data type to which the pointer is pointing (i.e. the width of the pointer – step).

    • 2. The unit of operation of a pointer is the width of the data type to which it points

    • 3. Pointers can be sized by if-else ratio because types can be converted to each other