搜索
bottom↓
回复: 23

KEIL C51中3个严重占程序空间的例子,请教解决办法。

[复制链接]

出90入0汤圆

发表于 2015-2-9 10:11:17 | 显示全部楼层 |阅读模式
本帖最后由 hzpyl 于 2015-2-10 20:19 编辑

51单片机,总共8K程序,程序容量不够了,
看汇编能不能省程序,发现3个严重占程序空间的例子。
请教解决办法。


============================================================================
实现功能:New_Hour除以10,商给temp_H,余给temp_M

C程序:
        U8 temp_H,temp_M;

        temp_H = New_Hour/10;
        temp_M = New_Hour%10;
        ........


KEIL C51生产汇编:
        MOV        A,040
        MOV        0F0,#00A        ;0F0为B
        DIV        AB
        MOV        R7,A

        MOV        A,040
        MOV        0F0,#00A        ;0F0为B
        DIV        AB
        MOV        R5,0F0        ;0F0为B

最佳:
        MOV        A,040
        MOV        0F0,#00A        ;0F0为B
        DIV        AB
        MOV        R7,A

        MOV        R5,0F0        ;0F0为B
=========================================================================
实现功能:temp高4位与低4位交换,或后给LCD_Buffer[10]

C程序:
        LCD_Buffer[10] |= (temp << 4) | (temp >> 4); ;

KEIL C51生产汇编:
        MOV        R7,A

        SWAP
        ANL        A,#0F0
        MOV        R6,A

        MOV        A,R7
        SWAP
        ANL        A,#0F0

        ORL        A,R6
        ORL        036,A

最佳:
        SWAP
        ORL        036,A
============================================================================
实现功能:4字节带C左移

C程序:
        YK_Data[3] = YK_Data[3]<<1;               
        if( (YK_Data[2] & 0x80)!=0 )
        {
                YK_Data[3] ++;
        }

        YK_Data[2] = YK_Data[2]<<1;
        if( (YK_Data[1] & 0x80)!=0 )
        {
                YK_Data[2] ++;
        }

        YK_Data[1] = YK_Data[1]<<1;
        if( (YK_Data[0] & 0x80)!=0 )
        {
                YK_Data[1] ++;
        }

        YK_Data[0] = YK_Data[0]<<1;
        if( b_c ==1 )
        {
                YK_Data[0] ++;
        }

这个论坛上好像讨论过,不知道有没有好办法?

论坛真是卧虎藏龙。
莫老大:我愿意每个问题给30莫元,以表谢意。
        第1个问题给7楼。
        第2个问题继续。
        第3个问题给11楼。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2015-2-9 10:19:31 | 显示全部楼层
就几个字节就觉得严重浪费的话,建议直接嵌入汇编

出90入0汤圆

 楼主| 发表于 2015-2-9 10:29:27 | 显示全部楼层
俗话说:一分钱难倒英雄汉。

不能换单片机,缺程序容量啊

出0入4汤圆

发表于 2015-2-9 10:36:54 | 显示全部楼层
最好的方法就是代码优化,次一点的就挂一个FLASH

出0入0汤圆

发表于 2015-2-9 12:47:14 | 显示全部楼层
hzpyl 发表于 2015-2-9 10:29
俗话说:一分钱难倒英雄汉。

不能换单片机,缺程序容量啊

8K超过了多少?超过的不多的话,每行每句的看。

出0入0汤圆

发表于 2015-2-9 12:52:10 | 显示全部楼层
那就产生asm文件,然后,优化汇编代码。

出0入93汤圆

发表于 2015-2-9 13:06:48 | 显示全部楼层
最简单的办法自然是提高优化等级,比如11级优化,Code优先。找不到11级优化的,自己将每一个可以打钩的地方都试一遍。
其次是换单片机。
再次是调用汇编。
再次是嵌入汇编。为什么这是个比上一个次一些呢,是嵌入汇编有一定的局限性,有时很可恶。
再次是直接访问特殊寄存器,产生不可预知的后果做到自己心中有数。Keil C51的优化能力也就那样了,抱怨是没有用的。
第一个:
  1. U8 temp_H,temp_M;
  2.         temp_H = New_Hour/10;
  3.         temp_M = New_Hour%10;
复制代码
修改成这个,你自己看看反汇编:
  1. U8 temp_H,temp_M;

  2.         temp_H = New_Hour/10;
  3.         temp_M = B;
复制代码


第二个:除了调用汇编外,没有好办法。

第三个:那么简单,你居然折腾的那么复杂……你觉得直接对unsigned long左移或循环左移不行吗

出90入0汤圆

 楼主| 发表于 2015-2-9 14:27:57 | 显示全部楼层
takashiki 发表于 2015-2-9 13:06
最简单的办法自然是提高优化等级,比如11级优化,Code优先。找不到11级优化的,自己将每一个可以打钩的地方 ...

谢谢takashiki

第一个问题,你的办法可行。

出90入0汤圆

 楼主| 发表于 2015-2-9 21:56:35 | 显示全部楼层
第3个问题,我用共同体试了一下。
union YK_Name { U32 YK32; U8 YK8[4]; } YK;

  YK32 <<=1;

仅省5个字节。效果不好。

出0入0汤圆

发表于 2015-2-10 08:34:15 | 显示全部楼层
我有的产品用4K flash的51,为省程序空间也是各种的优化,差钱的产品,麻烦啊。那优化,从来都是开到最高的,还有优化各种算法来省空间。

出0入0汤圆

发表于 2015-2-10 12:43:10 | 显示全部楼层
hzpyl 发表于 2015-2-9 21:56
第3个问题,我用共同体试了一下。
union YK_Name { U32 YK32; U8 YK8[4]; } YK;

第三个:

#define   rlcx(X)   CY=(bit)((X)&0x80), (X)=ACC    //产生 RLC X 指令,MOV A,X; RLC A; MOV X,A

CY = (bit)(YK[3] & 0x80);
        rlcx(YK[0]);
        rlcx(YK[1]);
        rlcx(YK[2]);
        rlcx(YK[3]);

运行结果:



反汇编代码:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出90入0汤圆

 楼主| 发表于 2015-2-10 13:50:36 | 显示全部楼层
BXAK 发表于 2015-2-10 12:43
第三个:

#define   rlcx(X)   CY=(bit)((X)&0x80), (X)=ACC    //产生 RLC X 指令,MOV A,X; RLC A; MO ...

请问,你用IAR还是keil
我用keil得不到你的程序。

麻烦你能给完整小程序吗?

出0入8汤圆

发表于 2015-2-10 14:04:07 来自手机 | 显示全部楼层
看看,有点意思

出90入0汤圆

 楼主| 发表于 2015-2-10 14:30:16 | 显示全部楼层
本帖最后由 hzpyl 于 2015-2-10 14:32 编辑

#define        rlcx(X)        ACC=(X),CY=(bit)((X)&0x80),(X)=ACC     //产生 RLC X 指令,MOV A,X; RLC A; MOV X,A

//==================================================================
void YK_Data_in_bit(bit b_c)
{
        bit        CY;

        CY = b_c;
        rlcx(YK_Data[0]);
        rlcx(YK_Data[1]);
        rlcx(YK_Data[2]);
        rlcx(YK_Data[3]);

============================================================

  38: void YK_Data_in_bit(bit b_c)
    39: {
    40:         bit     CY;
    41:  
    42:         CY = b_c;
C:0x180B    A210     MOV      C,0x22.0
C:0x180D    9211     MOV      0x22.1,C
    43:         rlcx(YK_Data[0]);
C:0x180F    E523     MOV      A,YK_Data(0x23)
C:0x1811    33       RLC      A
C:0x1812    9211     MOV      0x22.1,C
C:0x1814    F523     MOV      YK_Data(0x23),A
    44:         rlcx(YK_Data[1]);
C:0x1816    E524     MOV      A,0x24
C:0x1818    33       RLC      A
C:0x1819    9211     MOV      0x22.1,C
C:0x181B    F524     MOV      0x24,A
    45:         rlcx(YK_Data[2]);
C:0x181D    E525     MOV      A,0x25
C:0x181F    33       RLC      A
C:0x1820    9211     MOV      0x22.1,C
C:0x1822    F525     MOV      0x25,A
    46:         rlcx(YK_Data[3]);
C:0x1824    E526     MOV      A,0x26
C:0x1826    33       RLC      A
C:0x1827    9211     MOV      0x22.1,C
C:0x1829    F526     MOV      0x26,A

程序可以。
但每句多了一个MOV      0x22.1,C

出0入0汤圆

发表于 2015-2-10 17:22:48 来自手机 | 显示全部楼层
4字节带C左移

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-2-10 18:03:40 | 显示全部楼层
使用联合并把变量定义在BDATA区,先32位左移,然后再把CY送给最低字节的最低位

出0入0汤圆

发表于 2015-2-10 18:54:23 | 显示全部楼层
hzpyl 发表于 2015-2-10 14:30
#define        rlcx(X)        ACC=(X),CY=(bit)((X)&0x80),(X)=ACC     //产生 RLC X 指令,MOV A,X; RLC A; MOV X,A

/ ...

CY是51自身的进位标志位,不要另定义bit CY(不然会多出你上面的代码)

出90入0汤圆

 楼主| 发表于 2015-2-10 19:49:41 | 显示全部楼层
本帖最后由 hzpyl 于 2015-2-10 20:04 编辑
BXAK 发表于 2015-2-10 18:54
CY是51自身的进位标志位,不要另定义bit CY(不然会多出你上面的代码)


#define        rlcx(X)                ACC=(X),CY=(bit)((X)&0x80),(X)=ACC        //产生 RLC X 指令,MOV A,X; RLC A; MOV X,A

void YK_Data_in_bit(bit b_c)
{
//        bit        CY;

        CY = b_c;
        rlcx(YK_Data[0]);
        rlcx(YK_Data[1]);
        rlcx(YK_Data[2]);
        rlcx(YK_Data[3]);

去掉CY定义,编译会报警:
INT_YK.c(33): error C202: 'CY': undefined identifier
INT_YK.c(34): error C202: 'CY': undefined identifier
INT_YK.c(35): error C202: 'CY': undefined identifier
INT_YK.c(36): error C202: 'CY': undefined identifier
INT_YK.c(37): error C202: 'CY': undefined identifier
compiling Key_Scan.c...
compiling LCD.c...
compiling OUT.c...
compiling Public.c...
compiling IIC_RTC.c...
目标未创建

好意思,头文件没有定义CY,定义好后,OK了。
增加定义如下:
sfr                        PSW                = 0xD0;        //程序状态字:Bit7    Bit6    Bit5    Bit4    Bit3    Bit2    Bit1    Bit0
                                                //位描述:     CY      AC      F0      RS1     RS0     OV      F1      P
        sbit CY         =   PSW^7;      //进位标志
        sbit AC         =   PSW^6;      //辅助进位标志
        sbit F0         =   PSW^5;      //用户标志
        sbit RS1        =   PSW^4;      //寄存器组选择位1
        sbit RS0        =   PSW^3;      //寄存器组选择位0
        sbit OV         =   PSW^2;      //溢出标志
        sbit P          =   PSW^0;      //ACC的偶校验位

出0入0汤圆

发表于 2015-2-11 06:38:49 来自手机 | 显示全部楼层
汇编都知道怎么写了,就直接嵌汇编不就完事了。_asm

出90入0汤圆

 楼主| 发表于 2015-2-12 21:02:08 | 显示全部楼层
本帖最后由 hzpyl 于 2015-2-12 21:04 编辑

原来是伪本征函数
给个资料



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出90入0汤圆

 楼主| 发表于 2015-3-13 08:21:47 | 显示全部楼层
U8 code SWAP_ACC[] = {0xC4,0x22};                // C4   SWAP A    22 RET

        ACC = LCD_Tab_Small[Disp_L];
        (*(void (*)())((void *)SWAP_ACC))();
        LCD_Buffer[10] |= ACC;


===========================================================
U8 code SWAP_ACC[] = {0xC4,0x22};                // C4   SWAP A    22 RET
生成:
    swap  acc
       ret

(*(void (*)())((void *)SWAP_ACC))();
生成:
  rcall  SWAP_ACC


         

出0入0汤圆

发表于 2015-3-24 09:37:04 | 显示全部楼层
大侠们加油

出0入131汤圆

发表于 2015-3-24 09:41:34 | 显示全部楼层
就这优化不了多少空间吧? 多次计算的 写成函数,多次调用,以牺牲速度换取空间

出0入0汤圆

发表于 2015-10-2 22:05:37 | 显示全部楼层
学习了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-3 00:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表