View previous topic :: View next topic |
Author |
Message |
Zer0flag Guest
|
Using unsigned and signed operands |
Posted: Mon Aug 13, 2007 8:31 am |
|
|
Hello!
I have two variables:
Code: |
long ul;
signed int si;
|
Now I add si (which can be positive or negative) to lu and need to make sure that ul does not drop below zero. Because ul is unsigned and I cannot simply add si to ul and do the comparison after that, I do the following:
Code: |
if ((ul + si) < 0)
ul = 0;
else
ul += si;
|
This seems to work (at least at first glance) but from the CCS C manual I could not exactly figure out how it works. The compiler seems to do some type conversions here.
Can anyone give me a hint?
Thanks a lot,
Zer0flag |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Mon Aug 13, 2007 2:07 pm |
|
|
You might have to watch the case where ul is just below 0xFFFF - then ul + si will overflow. In general the compiler should generate code to so that there is never any overflow - so for (ul + si), result 'should' be 32 bit, and then sign-converted to allow comparison with zero.
Maybe something like:
Code: | if (si < 0) {
if (-si > ul)
ul = 0;
else
ul += si;
} else {
if(ul - si < 0xFF)
ul = 0xFFFF;
else
ul += si;
} |
|
|
|
Zer0flag Guest
|
|
Posted: Mon Aug 13, 2007 3:36 pm |
|
|
Thanks for the help SET. I also think that the compiler actually uses 32 bit signed to make the comparison work.
You mean the following code is generated internally by the compiler or did I misunderstand you:
SET wrote: |
Maybe something like:
Code: | if (si <0> ul)
ul = 0;
else
ul += si;
} else {
if(ul - si < 0xFF)
ul = 0xFFFF;
else
ul += si;
} |
|
|
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Mon Aug 13, 2007 4:28 pm |
|
|
Look at the assembly code in the .lst file to be sure. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Tue Aug 14, 2007 4:52 am |
|
|
The compiler may well do it in a number of ways - extend numbers to 32 bit, or perhaps along the lines I suggested - if you actually code it that way then at least you know what is happening. As Doug says though, best to read the actual compiler output! |
|
|
Zer0flag Guest
|
|
Posted: Tue Aug 14, 2007 12:37 pm |
|
|
I am trying to analyze the assembler output but I am new to assembler and it can take a while ;) Here is the output if someone else is interested:
Code: |
.................... if ((CurrentSet.i16 + enc_dir) < 0) // to handle multiple turns of the encoder
1110: CLRF @7A
1111: MOVF 43,W
1112: MOVWF @77
1113: BTFSC @77.7
1114: DECF @7A,F
1115: ADDWF 5B,W
1116: BSF STATUS.RP0
1117: MOVWF 44
1118: BCF STATUS.RP0
1119: MOVF 5C,W
111A: BSF STATUS.RP0
111B: MOVWF 45
111C: MOVF @7A,W
111D: BTFSC STATUS.C
111E: INCFSZ @7A,W
111F: ADDWF 45,F
1120: BTFSS 45.7
1121: GOTO 127
.................... CurrentSet.i16 = 0;
1122: BCF STATUS.RP0
1123: CLRF 5C
1124: CLRF 5B
.................... else
1125: GOTO 131
1126: BSF STATUS.RP0
.................... CurrentSet.i16 += enc_dir;
1127: CLRF @7A
1128: BCF STATUS.RP0
1129: MOVF 43,W
112A: BTFSC 43.7
112B: DECF @7A,F
112C: ADDWF 5B,F
112D: MOVF @7A,W
112E: BTFSC STATUS.C
112F: INCFSZ @7A,W
1130: ADDWF 5C,F
|
|
|
|
|