We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I wrote a program compress time to long. But some output give to much ( outout asm ). How can I reduce unuse code. see output below. my source.
extern unsigned char convBcd2Hex(unsigned char c); void convert( void ) { unsigned long dwTmp; dwTmp = convBcd2Hex( sClock[YEAR] ); // 4 year _lrol_( dwTmp, 4 ); dwTmp = dwTmp | convBcd2Hex( sClock[MONTH] ); // 4 month _lrol_( dwTmp, 5 ); dwTmp = dwTmp | convBcd2Hex( sClock[DAY] ); // 5 day _lrol_( dwTmp, 5 ); dwTmp = dwTmp | convBcd2Hex( sClock[HOUR] ); // 5 hour _lrol_( dwTmp, 6 ); dwTmp = dwTmp | convBcd2Hex( sClock[MINUTE]); // 6 minute _lrol_( dwTmp, 6 ); dwTmp = dwTmp | convBcd2Hex( sClock[SECOND]); // 6 second }
; SOURCE LINE # 140 001F AF00 E MOV R7,sClock+06H 0021 120000 R LCALL _convBcd2Hex 0024 E4 CLR A 0025 8F00 R MOV dwTmp+03H,R7 0027 F500 R MOV dwTmp+02H,A 0029 F500 R MOV dwTmp+01H,A 002B F500 R MOV dwTmp,A ; SOURCE LINE # 141 002D AE00 R MOV R6,dwTmp+02H 002F AD00 R MOV R5,dwTmp+01H 0031 AC00 R MOV R4,dwTmp 0033 7804 MOV R0,#04H 0035 120000 E LCALL ?C?LROL 0038 AF00 E MOV R7,sClock+05H 003A 120000 R LCALL _convBcd2Hex 003D E4 CLR A 003E EF MOV A,R7 003F 4500 R ORL A,dwTmp+03H 0041 F500 R MOV dwTmp+03H,A 0043 E500 R MOV A,dwTmp+02H + 0045 F500 R MOV dwTmp+02H,A | 0047 E500 R MOV A,dwTmp+01H |-- How can I reduct this code? 0049 F500 R MOV dwTmp+01H,A | 004B E500 R MOV A,dwTmp | 004D F500 R MOV dwTmp,A + ; SOURCE LINE # 142 004F AF00 R MOV R7,dwTmp+03H 0051 AE00 R MOV R6,dwTmp+02H 0053 AD00 R MOV R5,dwTmp+01H 0055 FC MOV R4,A 0056 7805 MOV R0,#05H 0058 120000 E LCALL ?C?LROL 005B AF00 E MOV R7,sClock+04H 005D 120000 R LCALL _convBcd2Hex 0060 E4 CLR A 0061 EF MOV A,R7 0062 4500 R ORL A,dwTmp+03H 0064 F500 R MOV dwTmp+03H,A 0066 E500 R MOV A,dwTmp+02H + 0068 F500 R MOV dwTmp+02H,A | 006A E500 R MOV A,dwTmp+01H |-- How can I reduct this code? 006C F500 R MOV dwTmp+01H,A | 006E E500 R MOV A,dwTmp | 0070 F500 R MOV dwTmp,A +
void convert( void ) { unsigned long dwTmp; dwTmp = convBcd2Hex( sClock[YEAR] ); // 4 year _lrol_( dwTmp, 4 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[MONTH] ); // 4 month _lrol_( dwTmp, 5 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[DAY] ); // 5 day _lrol_( dwTmp, 5 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[HOUR] ); // 5 hour _lrol_( dwTmp, 6 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[MINUTE]); // 6 minute _lrol_( dwTmp, 6 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[SECOND]); // 6 second }
Shorter code that does the wrong thing is no good at all. Sorry, my previous reply OR's into the MSB not the LSB like I was expecting. I should have checked the resulting code a bit closer.
I could not give you a correct reply to your question, but I can give you a correction to a problem. I don't think your usage of _lrol_() is going to do what you want as it stands right now. The manual does not indicate that _lrol_() rotates its long argument "in place". The manual says that _lrol_() returns the rotated value, so you would want to assign the return value back to dwTmp or use the return value as part of the OR expression.
What optimiser setting are you using? Note that _lrol_ is not compiled inline - contrary to what it says in the manual! See http://www.keil.com/forum/msgpage.asp?Offset=-1&MsgID=3914 I think the Keil _lrol_ is be rather inefficient - try a search for previous discussions?
Even the best compilers will generate some unnecessary code - it can be very frustrating especially if you come from an assembly language background. You are not using _lrol_ in quite the right way, although that is not the root of your question. It looks like the compiler is casting the return value of convBcd2Hex() an insists on "going through the motions" when performing an OR. Have you tried using a union between a long and a structure with bit fields defined for each of the components year, month day... etc. It would look something like this:
typedef struct { unsigned char year :5 unsigned char month :4 unsigned char day :5 unsigned char hour :6 unsigned char minute :6; unsigned char second :6; } date_time_record_type; typedef union { unsigned long l; date_time_record_type t; } date_time_type; .... date_time_type dwTmp; .... dwTmp.t.month = convBcd2Hex( sClock[MONTH] ); ....
Have you tried using optimizer level 9? Jon
I think we go wrong way. The problem is not in _lrol_(). It is in OR operation unsigned long and unsigned char. I use optimizer level 8. but i will try level 9. Thank for Graham Cole about c structure. But i already try it. It take more memory space than i think see below. I want to keep time in memory for time log. So I want optimize space. thank you.
typedef struct { unsigned char year :4; unsigned char month :4; unsigned char day :5; unsigned char hour :5; unsigned char minute :6; unsigned char second :6; } date_time_record_type; typedef union { unsigned long l; date_time_record_type t; } date_time_type; date_time_type dwTmp;
dwTmp. . . . . . . . . . . . . . . . . PUBLIC DATA UNION 0000H 5 date_time_record_type. . . . . . . . . TYPEDEF ----- STRUCT ----- 5 <-- use 5 byte not 4 byte year . . . . . . . . . . . . . . . . MEMBER ----- FIELD 0000H 4.0 month. . . . . . . . . . . . . . . . MEMBER ----- FIELD 0000H 4.4 day. . . . . . . . . . . . . . . . . MEMBER ----- FIELD 0001H 5.0 hour . . . . . . . . . . . . . . . . MEMBER ----- FIELD 0002H 5.0 minute . . . . . . . . . . . . . . . MEMBER ----- FIELD 0003H 6.0 second . . . . . . . . . . . . . . . MEMBER ----- FIELD 0004H 6.0
As ever, if you really must squeeze the last drop of effecieny, you need to write very carefully in Assembler. When you use 'C' (or any other high-level languae) you trade absolute control of the generated code for ease of writing & maintaining the source code.