The Master said, “The superior man is frank; the mean man is affectionate.” Analects of Confucius: A review
A hundred blog series. This paper is: the v22. Xx HongMeng kernel source code analysis (assembly) | where the CPU clock in
Hardware architecture:
- V22. Xx HongMeng kernel source code analysis (assembly) | where the CPU clock in
- V23. Xx HongMeng kernel source code analysis (assembly parameter) | how to transfer the parameters of the complex
- V36. Xx HongMeng kernel source code analysis (operating mode) | CPU is inspired, seven wives
- V38. Xx HongMeng kernel source code analysis (register) | jack Bauer is the busiest storage universe
- Abnormal v39. Xx HongMeng kernel source code analysis (over) | society is very simple, complex people
- V40. Xx HongMeng kernel source code analysis (assembly summary) | assembly and lovely as the girl next door
- V42. Xx HongMeng kernel source code analysis (interrupt switch) | system dynamic due to interrupt
- V43. Xx HongMeng kernel source code analysis (interrupt concept) | sea father-in-law’s daily work
- V44. Xx HongMeng kernel source code analysis (interrupt management) | henceforth no longer afraid of interruption
This article through dismantling a very simple assembly code to quickly understand assembly, for reading hongmeng assembly foundation. The rest of this series will examine the hongmeng assembler one by one.
Assembly is simple
-
First: to identify assembly language must be simple, no deep things, nothing more than moving data around, runtime data mainly stay in two places: memory and registers. The register is the internal memory of the CPU, closest to the arithmetic unit, so it is the fastest.
-
The second: The space provided by the user program is called the user stack. The sensitive work of the CPU should be brought back to the company to do. The sensitive work is called the kernel stack. The essence of a system call is that the CPU needs to switch the working mode, i.e. switch the office space.
-
Third: the CPU is pipelined, it only recognizes instructions, and only goes to one place (to the code section of the PC register) to get the instructions to digest. Instruction sets tell the outside world what the CPU can do and provide conversational instructions. Assembly language is a common language that people and CPUS can communicate happily without stumbling. One by one corresponding CPU instructions, and can ensure that the human memory is not good to modular design idea, first look at a section of C compiled into assembly code and then modular.
Square (C -> Assembler)
// compiler: armv7-a clang (trunk)
/ / + + + + + + + + + + + + square (c - > assembly) + + + + + + + + + + + + + + + + + + + + + + + +
int square(intA,int b){
return a*b;
}
square(int.int):
sub sp, sp, #8@ sp minus8To allocate stack space to square, only2STR r0, [sp, #4[sp] @ldr R1, [sp, #4[sp] @ fetch the first parameter to R1 LDR R2, [sp] @ fetch the second parameter to R2 mul r0, R1, r2 @ execute a*b to r0, return the work is always to r0 add sp, sp, #8The @ subroutine returns, equivalent to mov PC, lr, that is, jumps to the call pointCopy the code
Fp (C -> assembler)
/ / + + + + + + + + + + + + fp (c - > assembly) + + + + + + + + + + + + + + + + + + + + + + + +
int fp(int b)
{
int a = 1;
return square(a + b, a + b); }fp(int):
push {r11, lr} @r11(fp)/ LR, save main mov r11, sp @r11 used to save sp value, function stack start position sub sp, sp, #8@ sp minus8To allocate stack space to FP, only2STR r0, [sp, #4] @ save the parameter value and put it in SP+4Mov r0, #1 @r0=1STR r0, [sp] @1[SP] @ give the value of SP to r0 LDR r1, [SP, #4] @ SP +4Add R1, r0, R1 @ execute R1 =a+b mov r0, R1 @r0= R1, pass the parameter bl with r0, R1square(int.intMov LR, PC, mov PCsquare(int.intPop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @Copy the code
Main (c -> assembler)
/ / + + + + + + + + + + + + the main (c - > assembly) + + + + + + + + + + + + + + + + + + + + + + + +
int main(a)
{
int sum = 0;
for(int a = 0; a <100; a++){
sum = sum + fp(a);
}
return sum;
}
main:
push {r11, lr} @r11(fp)/ LR, mov r11, sp @r11 used to save sp value, function stack start position sub sp, sp, #16@ sp minus16Allocate stack space to main4Stack space to complete the calculation mov R0, #0@ initialize r0 STR r0, [r11, #4 -] @ Execute sum =0}, p, p8] @sum will always occupy SP+8STR r0, [sp, #4@a will always occupy SP+4LBB1_1: @ loop start entry LDR r0, [sp, #4] @ fetch a value to r0 CMP r0, #99@ with99Compare BGT. LBB1_4@ greater than99Mov pc.lbb1_4b.LBB1_2 @ To continue the loop, directly mov PC.lbb1_2.LBB1_2: @ to meet the loop condition8R0, sp+8LDR r0, [sp, #] LDR r0, [sp, #4[@r0 is used to pass the parameter, fetching the value of A to r0 as the parameter bl of fpfp(intMov LR, PC, mov PCfp(int[sp] @ add r0, r0, r1 @ calculate the new SUM, r0 save STR r0, [sp, #8Save the new sum to SP+8Mov pc.lbb1_3.LBB1_3: @ to complete a++ operation entry4] @SP+4The record is the value of a, and assign r0 add r0, r0, #1@ r0 increase1}, p, p4@ puts the new a value back into SP+4B.LBB1_1 @ jump to compare a <100At.lbb1_4: @ loop end entry LDR r0, [sp, #8Pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @pop {r11, lr} @ Jumping to LR is equivalent to MOV PC, LRCopy the code
The code is a bit long, all annotated, if you can directly understand so congratulations, hongmeng kernel based on the six assembler file also understand. This is the full view of the following C file
File picture
#include <stdio.h>
#include <math.h>
int square(intA,int b){
return a*b;
}
int fp(int b)
{
int a = 1;
return square(a + b, a + b); }int main(a)
{
int sum = 0;
for(int a = 0; a <100; a++){
sum = sum + fp(a);
}
return sum;
}
Copy the code
The code is simple and anyone can understand it, it’s typical, it’s representative, it has loops, it has judgments, it has operations, it has multilevel function calls. The structure of the compiled assembly code is not much different from that of C language. The difference is that the realization of the loop uses four modules, which are easy to understand: one is the start block (LBB1_1), a conditional processing block (LBB1_2), a conditional change block (LBB1_3), and the last end block (LBB1_4).
Block by block.
Let’s start with the shortest one
int square(intA,int b){
return a*b;
}
/ / compiled into
square(int.int):
sub sp, sp, #8@ sp minus8To allocate stack space to square, only2STR r0, [sp, #4[sp] @ldr R1, [sp, #4[sp] @ fetch the first parameter to R1 LDR R2, [sp] @ fetch the second parameter to R2 mul r0, R1, r2 @ execute a*b to r0, return the work is always to r0 add sp, sp, #8The @ subroutine returns, equivalent to mov PC, lr, that is, jumps to the call pointCopy the code
Sub sp, sp, #8 = sp-8, sp = sp-8, sp = sp-8, sp = sp-8, sp = sp-8, sp = sp-8, sp = sp-8 The code and the hongmeng kernel stack way, are used to decrease the full stack (FD). What is decreasing full stack? Decrement means that the address at the bottom of the stack is higher than the address at the top of the stack, and the growth direction of the stack is decreasing. Full means that the SP pointer always points to the top of the stack. Each function has its own independent bottom and top of the stack, and the space between them is called the stack frame. Sub sp, sp, #8 = 2 stack space, each stack space is four bytes. Do you want to release it? Add sp sp #8 to free up stack space. [sp, #4] [sp, #4] [sp, #4] [sp, #4] [sp, #4] [sp, #4] [sp, #4] [sp, #4] Be sure to understand decrement full stack, that’s the key! Otherwise you can’t read kernel assembly code.
The participation way
Generally through the register (r0.. R10) passes the parameter to (r0.. r10)
Add r1, r0, r1 @ run r1=a+b mov r0, r@r0 =r1, pass the parameter bl with r0, R1square(int.intMov LR, PC, mov PCsquare(int.int)
Copy the code
When in square, r0, R1, r0, r1, r0, r1, r0, r1, r0, R1, r0, R1
}, p, p4[sp] @ holds the first parameter STR R1, [sp] @ holds the second parameter LDR r1, [sp, #4[sp] @ : [sp] @ : [sp] @ : [sp] @ : [sp] @ : [sp] @ : [sp] @ : [sp] @ : [sp] @ : [spCopy the code
This is a process problem. The compiler saves parameters first, and it doesn’t matter how you want to use it. In addition, the return value is saved to R0 by default. Square gives the result of (a*b) to R0, and returns r0 to FP, which is the return value of square for FP.
Function calls to main and FP require other functions to be called, so both appear
Push {r11, lr}//....Pop {r11, lr}Copy the code
Fp saves the stack frame range and instruction position of main. Lr saves the position of instruction to which main function is executed. R11 points to the top of the stack. In this way, when FP returns to main after execution, the values of mov PC, LR and PC registers change, indicating that the code executed has changed, and the instructions and stack frames of main are returned to continue the unfinished work.
How to move the memory and register data?
Data stays primarily in two places: memory and registers. Register <-> register, memory <-> register, memory <-> memory handling instructions are different.
STR r1, [sp] @ Register -> memory4] @memory -> registerCopy the code
This is another pair, used between memory <-> registers, known as MOV R0, and R1 for register <-> registers
Ask three questions
First: What if it’s a mutable parameter? How to complete 100 parameters? There are only 12 parameters through the register
Second: Can there be more than one return value?
Third: can data be transported without passing through the CPU?
Intensive reading of the kernel source code
Four code stores synchronous annotation kernel source code, >> view the Gitee repository
Analysis of 100 blogs. Dig deep into the core
Add comments to hongmeng kernel source code process, sort out the following article. Content based on the source code, often in life scene analogy as much as possible into the kernel knowledge of a scene, with a pictorial sense, easy to understand memory. It’s important to speak in a way that others can understand! The 100 blogs are by no means a bunch of ridiculously difficult concepts being put forward by Baidu. That’s not interesting. More hope to make the kernel become lifelike, feel more intimate. It’s hard, it’s hard, but there’s no turning back. 😛 and code bugs need to be constantly debug, there will be many mistakes and omissions in the article and annotation content, please forgive, but will be repeatedly amended, continuous update. Xx represents the number of modifications, refined, concise and comprehensive, and strive to create high-quality content.
Compile build | The fundamental tools | Loading operation | Process management |
---|---|---|---|
Compile environment The build process Environment script Build tools Designed.the gn application Ninja ninja |
Two-way linked list Bitmap management In the stack way The timer Atomic operation Time management |
The ELF format The ELF parsing Static link relocation Process image |
Process management Process concept Fork Special process Process recycling Signal production Signal consumption Shell editor Shell parsing |
Process of communication | Memory management | Ins and outs | Task management |
spinlocks The mutex Process of communication A semaphore Incident control The message queue |
Memory allocation Memory management Memory assembly The memory mapping Rules of memory Physical memory |
Total directory Scheduling the story Main memory slave The source code comments Source structure Static site |
The clock task Task scheduling Task management The scheduling queue Scheduling mechanism Thread concept Concurrent parallel The system calls Task switching |
The file system | Hardware architecture | ||
File concept The file system The index node Mount the directory Root file system Character device VFS File handle Pipeline file |
Compilation basis Assembly and the cords Working mode register Anomaly over Assembly summary Interrupt switch Interrupt concept Interrupt management |
HongMeng station | into a little bit every day, the original is not easy, welcome to reprint, please indicate the source.