PDA

View Full Version : Save some bytes in program memory



Ioannis
- 4th February 2012, 20:48
Say you want to increment a variable and check the upper limit.

One way is this:


if index<3 then
index=index+1
else
index=0
endif


which compiles for a 16F877 to 16 bytes.

Using this one:


index=index+1 & 3


compiles to 12 bytes.

And even better:


index=index+1
index=index & 3


compiles to 7 bytes only!

Ioannis

P.S. Thanks to Mike K8LH for spotting a typo error.

Mike, K8LH
- 8th February 2012, 04:39
I assume you mean 'words' instead of 'bytes'?

I tried a few variations using the free/lite version of BoostC, just for fun;



if(index < 3) // 7 words
index++; //
else //
index = 0; //



index = index++ & 3; // 6 words



index = ++index & 3; // 5 words



index = 3 & ++index; // 4 words



index++; // 3 words
index &= 3; //



index++; // 2 words
index.2 = 0; //


Now I'm really curious about the assembly code that PBP generated...

Ioannis
- 8th February 2012, 08:01
Hmm, what is the difference between your 2nd and 3rd example?

Finally is result the same for all cases?

My sense is that a good compiler should deal with all these more effectively.

Ioannis

pedja089
- 8th February 2012, 13:49
You can save some code space if you use multiple If condition instead one with multiple AND.
Example:

IF portb.0 AND portb.1 AND portb.2 AND portb.3 THEN
ENDIF '46words
But if you break that in multiple if's

IF portb.0 THEN
IF portb.1 THEN
IF portb.2 THEN
IF portb.3 then
ENDIF
ENDIF
ENDIF
ENDIF
Code is just 13 words.

Mike, K8LH
- 8th February 2012, 15:24
Hmm, what is the difference between your 2nd and 3rd example?

Oops! The second example post-increments the variable and isn't valid. Sorry!


Finally is result the same for all cases?

Yes, except for the second example which isn't valid.


My sense is that a good compiler should deal with all these more effectively.

That seems to be the difficult part for just about every compiler.

Mike, K8LH
- 8th February 2012, 16:02
You can save some code space if you use multiple If condition instead one with multiple AND.
Example:

IF portb.0 AND portb.1 AND portb.2 AND portb.3 THEN
ENDIF '46words
But if you break that in multiple if's

IF portb.0 THEN
IF portb.1 THEN
IF portb.2 THEN
IF portb.3 then
ENDIF
ENDIF
ENDIF
ENDIF
Code is just 13 words.

Wow! Big difference. Here's your first example (46 words) in BoostC -> 16 words;


if(portb.0 & portb.1 & portb.2 & portb.3)
nop();

if(portb.0 & portb.1 & portb.2 & portb.3)
00ED 01FD CLRF CompTempVar20
00EE 1C86 BTFSS gbl_portb,1
00EF 28F3 GOTO label14
00F0 1C06 BTFSS gbl_portb,0
00F1 28F3 GOTO label14
00F2 0AFD INCF CompTempVar20, F
00F3 label14
00F3 01FE CLRF CompTempVar21
00F4 1C7D BTFSS CompTempVar20,0
00F5 28F9 GOTO label15
00F6 1D06 BTFSS gbl_portb,2
00F7 28F9 GOTO label15
00F8 0AFE INCF CompTempVar21, F
00F9 label15
00F9 1D86 BTFSS gbl_portb,3
00FA 28FE GOTO label16
00FB 1C7E BTFSS CompTempVar21,0
00FC 28FE GOTO label16


nop();
00FD 0000 NOP
00FE label16


Your second example (13 words) in BoostC -> 8 words;

if(portb.0)
if(portb.1)
if(portb.2)
if(portb.3)
nop();


if(portb.0)
00DD 1C06 BTFSS gbl_portb,0
00DE 28E6 GOTO label12
if(portb.1)
00DF 1C86 BTFSS gbl_portb,1
00E0 28E6 GOTO label12
if(portb.2)
00E1 1D06 BTFSS gbl_portb,2
00E2 28E6 GOTO label12
if(portb.3)
00E3 1D86 BTFSS gbl_portb,3
00E4 28E6 GOTO label12

nop();
00E5 0000 NOP
00E6 label12

This variation only uses four words, which is pretty much how you might code it in assembler;

if(portb ^ 15)
nop();

if(portb ^ 15)
00E6 300F MOVLW 0x0F
00E7 0606 XORWF gbl_portb, W
00E8 1903 BTFSC STATUS,Z
00E9 28EB GOTO label13


nop();
00EA 0000 NOP
00EB label13


It looks like the moral is to try and avoid multiple operations within a single instruction statement (line).

Mike, K8LH
- 8th February 2012, 16:17
I was too quick on the trigger... That last example should be;


if((portb ^ 15) == 0)
nop();


if((portb ^ 15) == 0)
00E8 300F MOVLW 0x0F
00E9 0606 XORWF gbl_portb, W
00EA 1D03 BTFSS STATUS,Z
00EB 28ED GOTO label13


nop();
00EC 0000 NOP
00ED label13

Art
- 9th February 2012, 17:58
This variation only uses four words, which is pretty much how you might code it in assembler;
You could load portb into the temp variable, rotate it four times left, and check the value is b11110000,
and it wouldn't matter what was happening on the high bits of portb.

rsocor01
- 10th February 2012, 00:05
It looks like the moral is to try and avoid multiple operations within a single instruction statement (line).

Hmmm, I've never looked at it that way, but you might be right :lemo:.

Mike, K8LH
- 10th February 2012, 00:48
This variation only uses four words, which is pretty much how you might code it in assembler;You could load portb into the temp variable, rotate it four times left, and check the value is b11110000, and it wouldn't matter what was happening on the high bits of portb.

Is there some advantage doing it that way, Art?

Art
- 10th February 2012, 03:03
Only if there was something else going on with the 4 high bits of portb,
Otherwise any input on the high bits breaks the condition of portb ^ 15 = 0. or am I mistaken there?

Mike, K8LH
- 10th February 2012, 17:17
You're correct. Sorry I misunderstood, Art...