• keil c51的内部RAM(idata)动态内存管理程序(转)


    源:keil c51的内部RAM(idata)动态内存管理程序

      程序比较简单,但感觉比较有意思,个人认为有一定应用价值,希望大家有更好的思路和方法,互相促进。
      程序的基本思路是:在CPU堆栈指针SP以上的RAM区域,通过把堆栈指针SP上移若干个字节,把空出的RAM区域供用户使用,当用户在使用完后又可以把该RAM区域释放。
      头文件dmalloc51.h

    /*
    *********************************************************************************************************
    *                     C51内部RAM动态内存申请函数 ,动态内存释放函数
    *                        (c) Copyright 2004.6, LM7556,China
    *                              All Rights Reserved
    *
    *
    * 文件 : dmalloc51.h
    *********************************************************************************************************
    */
    
    //动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize)从RAM堆栈中开辟一段空间做变量区.
    //动态内存释放函数DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize)把动态内存分配的空间从堆栈中释放。
    
    /******************************** Define Messages *****************************************/
    #define CPU_PCLEN 2        //CPU 程序指针长度(字节数).
    #define RAM_SIZE 0x100    //CPU内部RAM字节数。
    #define MEM_OVER 0xff    //CPU内部RAM内存不够。
    #define NO_MEM_DEL 0xfe    //试图释放不存在的内存空间。
    #define MEM_DELETED 0xfd    //内存空间释放成功。
    
    typedef unsigned char idata DMEM8U;
    
    /************* 动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize) *********************/
    //该函数把堆栈SP向上移动dmsize字节空间,再返回指向该空间起始地址的指针,
    //入口参数;dmsize是需要分配的空间大小,以DMEM8U为单位。
    //          StkSize 需要给CPU预留的堆栈空间.
    //出口参数: 返回 STACK_OVER --- CPU内部RAM堆栈溢出,分配的空间不存在.
    //            如果成功则返回一个指针,该指针指向所分配空间(大小为dmsize)的起始地址。
    DMEM8U *dmalloc(DMEM8U dmsize,StkSize);
    
    /************ 动态内存释放函数 freedmalloc(DMEM8U *dmp,DMEM8U dmsize) *********************/
    //该函数把起始地址为dmp的空间(大小为dmsize)从堆栈中释放。
    //入口参数;dmsize是需要释放的空间大小,以DMEM8U为单位。
    //          dmp指针指向需要释放空间的起始地址.
    //出口参数: 返回MEM_DELETE --- 内存空间释放成功.
    //          返回NO_MEM_DEL --- 试图释放不存在的内存空间.
    DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize);

    主文件 : dmalloc51.c

    /*
    *********************************************************************************************************
    *                     C51内部RAM动态申请函数 ,动态释放函数
    *                      (c) Copyright 2004.6, LM7556,China
    *                            All Rights Reserved
    *
    *
    * 文件 : dmalloc51.c
    *********************************************************************************************************
    */
    
    #include    "dmalloc51.h"
    sfr SP    = 0x81;
    
    /************* 动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize) *********************/
    //动态内存申请函数DMEM8U *dmalloc(DMEM8U dmsize,StkSize)从RAM堆栈中开辟一段空间做变量区.
    //该函数把堆栈SP向上移动dmsize字节空间,再返回指向该空间起始地址的指针,
    //入口参数;dmsize是需要分配的空间大小,以DMEM8U为单位。
    //          StkSize 需要给CPU预留的堆栈空间.
    //出口参数: 返回 STACK_OVER --- CPU内部RAM堆栈溢出,分配的空间不存在.
    //            如果成功则返回一个指针,该指针指向所分配空间(大小为dmsize)的起始地址。
    DMEM8U *dmalloc(DMEM8U dmsize,StkSize) 
    {DMEM8U *p1,*p2,spbuf; unsigned int StkChk;
    
        StkChk=SP+dmsize+StkSize;
        if (StkChk>(RAM_SIZE-1)) {return MEM_OVER;}    //检查要申请的内存是否存在.
        spbuf=SP;
        spbuf-=CPU_PCLEN;
        p1=(DMEM8U*)spbuf;
        p2=p1+dmsize;
        spbuf=(DMEM8U)p2+CPU_PCLEN;
        SP=spbuf;
    //把上一级函数的返回地址移到该空间的上面,使本函数自己在执行完后可以正确的返回到上一级函数.
        p1++;p2++;
        *p2++=*p1++;
        *p2=*p1;
        p1--;
        return p1;
    }
    
    /************ 动态内存释放函数 freedmalloc(DMEM8U *dmp,DMEM8U dmsize) *********************/
    //动态内存释放函数DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize)把动态内存分配的空间从堆栈中释放。
    //该函数把起始地址为dmp的空间(大小为dmsize)从堆栈中释放。
    //入口参数;dmsize是需要释放的空间大小,以DMEM8U为单位。
    //          dmp指针指向需要释放空间的起始地址.
    //出口参数: 返回MEM_DELETE --- 内存空间释放成功.
    //          返回NO_MEM_DEL --- 试图释放不存在的内存空间.
    DMEM8U freedmalloc(DMEM8U *dmp,DMEM8U dmsize) 
    {DMEM8U *p1,*p2,spbuf,i;
    
        spbuf=(DMEM8U)dmp+dmsize;
        if (spbuf<=(DMEM8U)dmp) {return NO_MEM_DEL;}
        if (spbuf>SP-CPU_PCLEN) {spbuf=SP-CPU_PCLEN;}
        i=SP-spbuf;
        p1=(DMEM8U*)spbuf;
        p1++;
        p2=dmp;
        spbuf=(SP-spbuf)+p2;
        spbuf--;
        while (i)
        {
            *p2++=*p1++;    //把上一级函数的返回地址移到该空间的底部,使程序可以返回到上一级函数.
            i--;
        }
        SP=spbuf;
        return MEM_DELETED;
    }

      应用范例:

    文件 : main.c

    #include    <reg52.h>
    #include    <stdio.h>
    #include    <intrins.h>
    
    #define STACK_SIZE 0x30    //为程序预留的最小堆栈.
    #include    "dmalloc51.h"
    
    void initsio(void);
    void TDelay(unsigned int t);
    
    void Fn_dRamA(void);
    void Fn_dRamB(void);
    void Fn_dRamC(void);
    
    
    void main(void)
    {
        initsio();
        while (1)
        {
            TDelay(500); 
            Fn_dRamA();
            printf("
    ");
            TDelay(500); 
            Fn_dRamB();
            printf("
    ");
            TDelay(500); 
            Fn_dRamC();
            printf("
    ");
        }
    }
    
    #define dmSIZE_A 0x20
    void Fn_dRamA(void)
    {unsigned char i,*mp,*mpp;
        if ((mpp=dmalloc(dmSIZE_A,STACK_SIZE))==MEM_OVER) {return;};
        mp=mpp;
        for (i=0;i<dmSIZE_A-1;i++)
        {
            *mp++=i+0x20;
        }
        *mp=0;
        printf(mpp);
        printf("
    ");
        Fn_dRamB();
        freedmalloc(mpp,dmSIZE_A);    //后面加nop()为了防止c51把freedmalloc(mpp)做ljmp 调用。
        _nop_();
    }
    
    #define dmSIZE_B 0x20
    void Fn_dRamB(void)
    {unsigned char i,*mp,*mpp;
        if ((mpp=dmalloc(dmSIZE_B,STACK_SIZE))==MEM_OVER) {return;};
        mp=mpp;
        for (i=0;i<dmSIZE_B-1;i++)
        {
            *mp++=i+0x40;
        }
        *mp=0;
        printf(mpp);
        printf("
    ");
        Fn_dRamC();
        freedmalloc(mpp,dmSIZE_B);    //后面加nop()为了防止c51把freedmalloc(mpp)做ljmp 调用。
        _nop_();
    }
    
    #define dmSIZE_C 0x20
    void Fn_dRamC(void)
    {unsigned char i,*mp,*mpp;
    
        if ((mpp=dmalloc(dmSIZE_C,STACK_SIZE))==MEM_OVER) {return;};
        mp=mpp;
        for (i=0;i<dmSIZE_C-1;i++)
        {
            *mp++=i+0x60;
        }
        *mp=0;
        printf(mpp);
        printf("
    ");
        freedmalloc(mpp,dmSIZE_C);    //后面加nop()为了防止c51把freedmalloc(mpp)做ljmp 调用。
        _nop_();
    }
    
    void TDelay(unsigned int t)
    {unsigned int i,j;
        for (i=0;i<t;i++)
        {
            for (j=0;j<t;j++) {}
        }
    }
    
    void initsio(void) 
    {
       TMOD=TMOD&0x0F;
       TMOD=TMOD|0x20;
       TL1=0xFD,TH1=0xFD;//19200 , 22.1184MHz
       SCON=0x50;PCON=0x00;
       TR1=1;
       TI    = 1;                  /* TI:   set TI to send first char of UART    */
    }
  • 相关阅读:
    2018/2/26 省选模拟赛 0分
    2018/2/25 省选模拟赛 36分
    BZOJ 2428 JZYZOJ1533 : [HAOI2006]均分数据 模拟退火 随机化
    BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演
    BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap
    POJ 2728 JZYZOJ 1636 分数规划 最小生成树 二分 prim
    JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树
    POJ 3974 Palindrome 字符串 Manacher算法
    BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元
    jQuery cookie使用
  • 原文地址:https://www.cnblogs.com/LittleTiger/p/4384730.html
Copyright © 2020-2023  润新知