目录
一、C语言变量
本文用到ARM汇编指令,请参考:
本文用到编译器为在线编译器(ARM-GCC):
1、局部变量
1)、什么是局部变量
局部变量,顾名思义,只在局部区域有效的变量。
局部变量的空间开辟在栈中,在程序运行过程中动态开辟,局部变量的生命周期随着函数调用的开始而开始,随着函数调用的结束而结束。
2)、代码示例
#include <stdio.h>
int test_func(int param0, int param1)
{
int b = 4;
return b;
}
int main()
{
test_func(1, 3);
return 0;
}
编译后汇编如下:
test_func:
push {r7}
sub sp, sp, #20
add r7, sp, #0
str r0, [r7, #4]
str r1, [r7]
movs r3, #4
str r3, [r7, #12]
ldr r3, [r7, #12]
mov r0, r3
adds r7, r7, #20
mov sp, r7
ldr r7, [sp], #4
bx lr
main:
push {r7, lr}
add r7, sp, #0
movs r1, #3
movs r0, #1
bl test_func
movs r3, #0
mov r0, r3
pop {r7, pc}
3)、代码讲解
在test_func函数中定义局部变量b,且初始化为4,分析test_func汇编代码,如下图圈住地方(对应c语言的语句 int b = 4;):
将立即数4写入寄存器R3中,然后将R3寄存器中值写入栈(R7+12Byte处)中。完成局部变量的空间开辟以及值初始化。
2、全局变量
1)、什么是全局变量
全局变量是在代码文件中定义的全局变量,在整个源文件中皆可访问。如果要在其他源文件中使用该变量,需要使用extern关键字引用。
全局变量的空间开辟在全局变量区,全局变量的生命周期同程序的生命周期相同。
2)、代码示例
#include <stdio.h>
int a = 3;
int test_func(int param0, int param1)
{
int b = a;
return b;
}
int main()
{
test_func(1, 3);
return 0;
}
编译后汇编如下:
a:
.word 3
test_func:
push {r7}
sub sp, sp, #20
add r7, sp, #0
str r0, [r7, #4]
str r1, [r7]
movw r3, #:lower16:a
movt r3, #:upper16:a
ldr r3, [r3]
str r3, [r7, #12]
ldr r3, [r7, #12]
mov r0, r3
adds r7, r7, #20
mov sp, r7
ldr r7, [sp], #4
bx lr
main:
push {r7, lr}
add r7, sp, #0
movs r1, #3
movs r0, #1
bl test_func
movs r3, #0
mov r0, r3
pop {r7, pc}
3)、代码讲解
定义全局变量a,且初始化为3。在test_func函数中定义局部变量b且将全局变量a的值赋予局部变量b,分析汇编代码,如下图圈住地方(对应c语言的语句 int b = a;):
将全局变量a的地址写入寄存器R3中,然后将R3寄存器中所指向地址中的数据读取到R3寄存器中,然后将R3寄存器中值写入栈(R7+12Byte处)中。将局部变量b初始化成全局变量a的值。由以上分析可以看出全局变量并不像局部变量那样保存在栈上,而是定义在数据段上。
3、静态变量
1)、全局静态变量
全局静态变量是指定义在代码文件中的用static修饰的变量,静态全局变量存储在静态变量区,生命周期伴随程序的整个生命周期。只可在定义该变量的源文件中使用,不可在其他源文件中使用extern关键字引用该文件。
2)、局部静态变量
局部静态变量是指在函数内定义的使用static修饰的变量。局部全局变量存储在静态变量区,生命周期伴随程序的整个生命周期。尽可在定义该变量的函数内使用。
3)、代码示例
#include <stdio.h>
static int a = 5;
int test_func(int param0, int param1)
{
static int b = 2;
b++;
a++;
return b;
}
int main()
{
int ret = test_func(1, 3);
printf("b:%d\r\n", ret);
ret = test_func(1, 3);
printf("b:%d\r\n", ret);
return 0;
}
编译后汇编如下:
a:
.word 5
test_func:
push {r7}
sub sp, sp, #12
add r7, sp, #0
str r0, [r7, #4]
str r1, [r7]
movw r3, #:lower16:b.0
movt r3, #:upper16:b.0
ldr r3, [r3]
adds r2, r3, #1
movw r3, #:lower16:b.0
movt r3, #:upper16:b.0
str r2, [r3]
movw r3, #:lower16:b.0
movt r3, #:upper16:b.0
ldr r3, [r3]
mov r0, r3
adds r7, r7, #12
mov sp, r7
ldr r7, [sp], #4
bx lr
.LC0:
.ascii "b:%d\015\012\000"
main:
push {r7, lr}
sub sp, sp, #8
add r7, sp, #0
movs r1, #3
movs r0, #1
bl test_func
str r0, [r7, #4]
ldr r1, [r7, #4]
movw r0, #:lower16:.LC0
movt r0, #:upper16:.LC0
bl printf
movs r1, #3
movs r0, #1
bl test_func
str r0, [r7, #4]
ldr r1, [r7, #4]
movw r0, #:lower16:.LC0
movt r0, #:upper16:.LC0
bl printf
movs r3, #0
mov r0, r3
adds r7, r7, #8
mov sp, r7
pop {r7, pc}
4)、代码讲解
定义静态全局变量a,且初始化为5。在test_func函数中定义的静态局部变量b为,且初始化为2,分析汇编代码a++(绿框圈住)和b++(红框圈住)语句:
movw r3, #:lower16:b.0
movt r3, #:upper16:b.0 ; 将变量b的地址写入到R3寄存器
ldr r3, [r3];将b的值读取到寄存器R3中
adds r2, r3, #1;寄存器R3自增,结果保存到R2寄存器
movw r3, #:lower16:b.0
movt r3, #:upper16:b.0;将变量b的地址写入到R3寄存器
str r2, [r3];R2寄存器中运算结果写入R3寄存器中所指的地址中
变量a分析雷同。静态变量a与b的区别是a可以再整个源文件中访问,b只可以在函数test_func中访问。
4、const常量
1)、const变量
const变量,为只读变量,在编码过程中只可对该变量进行读,不可修改该变量的值。该变量会被存放在常量区,生命周期伴随程序的整个生命周期。
5、寄存器变量
1)、register变量
register变量,为寄存器变量,在编码过程中使用该变量修饰局部变量,告诉编译器将此变量尽量存储在寄存器中,编译器会根据现实情况,来尽可能的降该变量的存储空间开辟在CPU寄存器中,但不是绝对可以开辟在寄存器中。register关键字只可以用来修饰局部变量。
2)、代码示例
#include <stdio.h>
int test_func(int param0, int param1)
{
register int a = 5;
int b = a + 2;
return b;
}
int main()
{
test_func(1, 3);
return 0;
}
编译后汇编如下:
test_func:
push {r4, r7}
sub sp, sp, #16
add r7, sp, #0
str r0, [r7, #4]
str r1, [r7]
movs r4, #5
adds r3, r4, #2
str r3, [r7, #12]
ldr r3, [r7, #12]
mov r0, r3
adds r7, r7, #16
mov sp, r7
pop {r4, r7}
bx lr
main:
push {r7, lr}
add r7, sp, #0
movs r1, #3
movs r0, #1
bl test_func
movs r3, #0
mov r0, r3
pop {r7, pc}
3)、代码讲解
在test_func函数中定义寄存器局变量a,且初始化为5。定义局部变量b,且初始化为a+2,分析汇编代码(register int a = 5; int b = a + 2;)语句:
movs r4, #5;将立即数5写到寄存器R4中
adds r3, r4, #2;将R4中的值与立即数2相加,结果保存在寄存器R3中
str r3, [r7, #12];,将R3中运算结果保存到栈中(R7+12Byte处)。
由上分析可知,变量a被保存在寄存器中,变量b被保存在栈中。
二、总结
如有问题请批评指出,感谢!