KEIL C51中3个严重占程序空间的例子,请教解决办法。
本帖最后由 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
C程序:
LCD_Buffer |= (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 = YK_Data<<1;
if( (YK_Data & 0x80)!=0 )
{
YK_Data ++;
}
YK_Data = YK_Data<<1;
if( (YK_Data & 0x80)!=0 )
{
YK_Data ++;
}
YK_Data = YK_Data<<1;
if( (YK_Data & 0x80)!=0 )
{
YK_Data ++;
}
YK_Data = YK_Data<<1;
if( b_c ==1 )
{
YK_Data ++;
}
这个论坛上好像讨论过,不知道有没有好办法?
论坛真是卧虎藏龙。
莫老大:我愿意每个问题给30莫元,以表谢意。
第1个问题给7楼。
第2个问题继续。
第3个问题给11楼。 就几个字节就觉得严重浪费的话,建议直接嵌入汇编 俗话说:一分钱难倒英雄汉。
不能换单片机,缺程序容量啊 最好的方法就是代码优化,次一点的就挂一个FLASH hzpyl 发表于 2015-2-9 10:29
俗话说:一分钱难倒英雄汉。
不能换单片机,缺程序容量啊
8K超过了多少?超过的不多的话,每行每句的看。 那就产生asm文件,然后,优化汇编代码。 最简单的办法自然是提高优化等级,比如11级优化,Code优先。找不到11级优化的,自己将每一个可以打钩的地方都试一遍。
其次是换单片机。
再次是调用汇编。
再次是嵌入汇编。为什么这是个比上一个次一些呢,是嵌入汇编有一定的局限性,有时很可恶。
再次是直接访问特殊寄存器,产生不可预知的后果做到自己心中有数。Keil C51的优化能力也就那样了,抱怨是没有用的。
第一个:U8 temp_H,temp_M;
temp_H = New_Hour/10;
temp_M = New_Hour%10;修改成这个,你自己看看反汇编:U8 temp_H,temp_M;
temp_H = New_Hour/10;
temp_M = B;
第二个:除了调用汇编外,没有好办法。
第三个:那么简单,你居然折腾的那么复杂……你觉得直接对unsigned long左移或循环左移不行吗 takashiki 发表于 2015-2-9 13:06
最简单的办法自然是提高优化等级,比如11级优化,Code优先。找不到11级优化的,自己将每一个可以打钩的地方 ...
谢谢takashiki
第一个问题,你的办法可行。 第3个问题,我用共同体试了一下。
union YK_Name { U32 YK32; U8 YK8; } YK;
YK32 <<=1;
仅省5个字节。效果不好。
我有的产品用4K flash的51,为省程序空间也是各种的优化,差钱的产品,麻烦啊。那优化,从来都是开到最高的,还有优化各种算法来省空间。 hzpyl 发表于 2015-2-9 21:56
第3个问题,我用共同体试了一下。
union YK_Name { U32 YK32; U8 YK8; } YK;
第三个:
#define rlcx(X) CY=(bit)((X)&0x80), (X)=ACC //产生 RLC X 指令,MOV A,X; RLC A; MOV X,A
CY = (bit)(YK & 0x80);
rlcx(YK);
rlcx(YK);
rlcx(YK);
rlcx(YK);
运行结果:
反汇编代码:
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得不到你的程序。
麻烦你能给完整小程序吗? 看看,有点意思 本帖最后由 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);
rlcx(YK_Data);
rlcx(YK_Data);
rlcx(YK_Data);
============================================================
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);
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);
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);
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);
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 4字节带C左移 使用联合并把变量定义在BDATA区,先32位左移,然后再把CY送给最低字节的最低位 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(不然会多出你上面的代码)
本帖最后由 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);
rlcx(YK_Data);
rlcx(YK_Data);
rlcx(YK_Data);
去掉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的偶校验位
汇编都知道怎么写了,就直接嵌汇编不就完事了。_asm 本帖最后由 hzpyl 于 2015-2-12 21:04 编辑
原来是伪本征函数
给个资料
U8 code SWAP_ACC[] = {0xC4,0x22}; // C4 SWAP A 22 RET
ACC = LCD_Tab_Small;
(*(void (*)())((void *)SWAP_ACC))();
LCD_Buffer |= ACC;
===========================================================
U8 code SWAP_ACC[] = {0xC4,0x22}; // C4 SWAP A 22 RET
生成:
swapacc
ret
(*(void (*)())((void *)SWAP_ACC))();
生成:
rcallSWAP_ACC
大侠们加油{:victory:}{:victory:}{:victory:} 就这优化不了多少空间吧? 多次计算的 写成函数,多次调用,以牺牲速度换取空间 学习了。
页:
[1]