Referencia: https://blog.csdn.net/u012874587/article/details/78843940?utm_source=app&app_version=4.8.0
Después de leer el artículo de referencia primero, puede ser más fácil comprender algunas cosas básicas después de leerlas en el artículo anterior. ., omitido en este artículo.
El propósito de escribir este artículo es que la mayoría de los blogs simplemente publican el código ensamblador sin comentarios detallados, lo que me causó muchas dudas cuando lo leí yo mismo, así que escribí este artículo para aclarar algunas de las cosas sobre las que tengo dudas. Agregar comentarios
1. Primero, debe comprender la estructura del marco de la pila, como se muestra a continuación.
El puntero de la pila R11 generalmente es fp en ensamblador y sp apunta a la dirección de retorno
. 2. Código en lenguaje C
1 int foo(int a, int b, int c, int d)
2 {
3 int A,B,C,D;
4 A = a;
5 B = b;
6 C = c;
7 D = d;
8
9 return 0;
10 }
11 void main(void)
12 {
13 int a;
14 a = foo(1,2,3,4);
15 }
El código de desmontaje correspondiente es
1 00000000 <_start>:
2 .text
3 .global _start
4 _start:
5 ldr sp,=4096 ;声明栈空间大小为4096字节
6 0: e3a0da01 mov sp, #4096 ; 0x1000
7 bl main ;跳入main函数,进入c世界
8 4: eb000014 bl 5c <main>
9
10 00000008 <loop>:
11 loop:
12 b loop
13 8: eafffffe b 8 <loop>
14
15 0000000c <foo>: ;先从main函数看起,再根据跳转,读这部分代码
16 int foo(int a, int b, int c, int d)
17 {
18 c: e52db004 push {
fp} ; 保存栈指针压入栈中也就是上图中的R11。地址为sp-4(str fp, [sp, #-4]!)
19 10: e28db000 add fp, sp, #0 ;fp栈指针指向栈顶指针sp
20 14: e24dd024 sub sp, sp, #36 ; 留给栈空间大小为36个字节,具体栈空间分布情况见下图10x24
21 18: e50b0018 str r0, [fp, #-24]
22 1c: e50b101c str r1, [fp, #-28]
23 20: e50b2020 str r2, [fp, #-32]
24 24: e50b3024 str r3, [fp, #-36] ; 0x24
25 int A,B,C,D;
26 A = a;
27 28: e51b3018 ldr r3, [fp, #-24]
28 2c: e50b3014 str r3, [fp, #-20]
29 B = b;
30 30: e51b301c ldr r3, [fp, #-28]
31 34: e50b3010 str r3, [fp, #-16]
32 C = c;
33 38: e51b3020 ldr r3, [fp, #-32]
34 3c: e50b300c str r3, [fp, #-12]
35 D = d;
36 40: e51b3024 ldr r3, [fp, #-36] ; 0x24
37 44: e50b3008 str r3, [fp, #-8]
38
39 return 0;
40 48: e3a03000 mov r3, #0
41 }
42 4c: e1a00003 mov r0, r3 ;一般函数返回都是用R0进行传递
43 50: e28bd000 add sp, fp, #0 ;sp指针重新指向栈顶
44 54: e8bd0800 pop {
fp} ;fp出栈
45 58: e12fff1e bx lr
46
47 0000005c <main>:
48 void main(void)
49 {
50 5c: e92d4800 push {
fp, lr} ;压栈之后,fp指针指向sp-4的地址
51 60: e28db004 add fp, sp, #4 ;加4之后,fp指针指向栈顶Sp
52 64: e24dd008 sub sp, sp, #8 ;栈空间大小为8个字节,具体栈分布情况见下图2
53 int a;
54 a = foo(1,2,3,4);
55 68: e3a00001 mov r0, #1
56 6c: e3a01002 mov r1, #2
57 70: e3a02003 mov r2, #3
58 74: e3a03004 mov r3, #4
59 78: ebffffe3 bl c <foo>
60 7c: e1a03000 mov r3, r0
61 80: e50b3008 str r3, [fp, #-8]
62 }
63 84: e24bd004 sub sp, fp, #4
64 88: e8bd4800 pop {
fp, lr}
65 8c: e12fff1e bx lr