单片机 局部变量存储在R0-R7,简单的LED点亮试验,观察反汇编就课看出,但是C51只允许通过工作寄存器传递三个参数,其他参数通过固定存储区传递

局部变量空间,就是堆栈空间,也就是栈空间。

从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。

定义一个局部变量a,编译器会将a的地址分配到寄存器组R0~R7中去。由于它是局部变量,所以编译器将使用立即数赋值语句为代表a的寄存器Rn赋值,最后计算的结果也将存在寄存器组中,位置由编译器任意指定。

定义一个全局变量a,编译器将在RAM中为变量a指定一个专用地址,在C程序中给a赋的值将存入这个专用地址中。程序操作变量a时,首先从专用地址中取出存放的值,然后再进行计算。

结论:

局部变量由于用寄存器直接操作,存取速度和计算速度都很快;由于寄存器数量有限,如果局部变量过多,将使代码由于频繁分配寄存器而变得冗长。

全局变量被定义在内存中的专门地址上,存取位置固定。对于频繁存取的重要变量可以采用全局变量以减少代码的长度;由于全局变量总是占用内存,如果过多,或者把程序处理和计算中的一些中间变量也定义成全局变量,将大量消耗内存空间,处理速度会减慢,同时数据安全性也会降低。

接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明,默认都使用VC编译的release版。

首先,来了解一下 C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变量(Local),静态变量(Static)、寄存器变量(Regeister)。每种变量都有不同的分配方式。先来看下面这段代码:

include

int g1=0, g2=0, g3=0;

int main()

{

static int s1=0, s2=0, s3=0;

int v1=0, v2=0, v3=0;

//打印出各个变量的内存地址

printf(“0xx\n”,&v1); //打印各本地变量的内存地址

printf(“0xx\n”,&v2);

printf(“0xx\n\n”,&v3);

printf(“0xx\n”,&g1); //打印各全局变量的内存地址

printf(“0xx\n”,&g2);

printf(“0xx\n\n”,&g3);

printf(“0xx\n”,&s1); //打印各静态变量的内存地址

printf(“0xx\n”,&s2);

printf(“0xx\n\n”,&s3);

return 0;

}

编译后的执行结果是:

0x0012ff78

0x0012ff7c

0x0012ff80

0x004068d0

0x004068d4

0x004068d8

0x004068dc

0x004068e0

0x004068e4

输 出的结果就是变量的内存地址。其中v1,v2,v3是本地变量,g1,g2,g3是全局变量,s1,s2,s3是静态变量。你可以看到这些变量在内存是连 续分布的,但是本地变量和全局变量分配的内存地址差了十万八千里,而全局变量和静态变量分配的内存是连续的。这是因为本地变量和全局/静态变量是分配在不 同类型的内存区域中的结果。对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈 (stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然 代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数 据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。

补充:怎么让程序的全局变量不会漫天飞

1.使用结构体分类 
2.把全局变量放在一个.c里面 
3.如果外部函数要调用的话,就使用相应API(如cmSet_xxxxx() cmGet_xxxxx())

 

源程序

/*     名称:闪烁的LED
    说明:LED按设定的时间间隔闪烁
*/
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED=P1^0;
//延时
void DelayMS(uint x)
{
    uchar i;
    while(x--)
    {
        for(i=0;i<120;i++);
    }
}
//主程序
void main()
{
    while(1)
    {
        LED=~LED;
        DelayMS(150);
    }
}

反汇编

    126: ?C_STARTUP:     LJMP    STARTUP1 
   127:  
   128:                 RSEG    ?C_C51STARTUP 
   129:  
   130: STARTUP1: 
   131:  
   132: IF IDATALEN <> 0 
C:0x0000    020019   LJMP     STARTUP1(C:0019)
     9: void DelayMS(uint x) 
    10: { 
    11:         uchar i; 
    12:         while(x--) 
C:0x0003    EF       MOV      A,R7
C:0x0004    1F       DEC      R7
C:0x0005    AA06     MOV      R2,0x06
C:0x0007    7001     JNZ      C:000A
C:0x0009    1E       DEC      R6
C:0x000A    4A       ORL      A,R2
C:0x000B    600B     JZ       C:0018
    13:         { 
    14:                 for(i=0;i<120;i++); 
C:0x000D    E4       CLR      A
C:0x000E    FD       MOV      R5,A
C:0x000F    ED       MOV      A,R5
C:0x0010    C3       CLR      C
C:0x0011    9478     SUBB     A,#0x78
C:0x0013    50EE     JNC      DelayMS(C:0003)
C:0x0015    0D       INC      R5
C:0x0016    80F7     SJMP     C:000F
    15:         } 
    16: } 
    17: //主程序 
C:0x0018    22       RET      
   133:                 MOV     R0,#IDATALEN - 1 
C:0x0019    787F     MOV      R0,#0x7F
   134:                 CLR     A 
C:0x001B    E4       CLR      A
   135: IDATALOOP:      MOV     @R0,A 
C:0x001C    F6       MOV      @R0,A
   136:                 DJNZ    R0,IDATALOOP 
C:0x001D    D8FD     DJNZ     R0,IDATALOOP(C:001C)
   185:                 MOV     SP,#?STACK-1 
   186:  
   187: ; This code is required if you use L51_BANK.A51 with Banking Mode 4 
   188: ;<h> Code Banking 
   189: ; <q> Select Bank 0 for L51_BANK.A51 Mode 4 
   190: #if 0    
   191: ;     <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4. 
   192: EXTRN CODE (?B_SWITCH0) 
   193:                 CALL    ?B_SWITCH0      ; init bank mechanism to code bank 0 
   194: #endif 
   195: ;</h> 
C:0x001F    758107   MOV      SP(0x81),#0x07
   196:                 LJMP    ?C_START 
C:0x0022    020025   LJMP     main(C:0025)
    18: void main() 
    19: { 
    20:         while(1) 
    21:         { 
    22:                 LED=~LED; 
C:0x0025    B290     CPL      LED(0x90.0)
    23:                 DelayMS(150); 
C:0x0027    7F96     MOV      R7,#0x96
C:0x0029    7E00     MOV      R6,#0x00
C:0x002B    120003   LCALL    DelayMS(C:0003)
    24:         } 
C:0x002E    80F5     SJMP     main(C:0025)
C:0x0030    00       NOP      
C:0x0031    00       NOP      

 

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值