4
\$\begingroup\$

I'd like to know how many lines of C code in average corresponds to 1Ko programmable memory for PIC18F microcontrollers

Or how many lines of assembly instructions ?

\$\endgroup\$
7
  • 4
    \$\begingroup\$ None. I filled it with data instead. \$\endgroup\$ Commented Apr 25, 2015 at 14:28
  • 4
    \$\begingroup\$ There is nothing opinion based about the answer to this question. It is an easy factual statement. \$\endgroup\$
    – Passerby
    Commented Apr 25, 2015 at 16:52
  • 3
    \$\begingroup\$ I'm with @Passerby, there is no opinion involved! It may be argued that the questioner is clueless about the translation process from an high level language like C to machine language, but the potential answers are not a matter of opinion at all! If I could, I would vote to reopen. \$\endgroup\$ Commented Apr 25, 2015 at 17:32
  • 1
    \$\begingroup\$ @LorenzoDonati This depends a lot on the qualities of the C code. On a PIC, a function call takes more instructions than ++i; It's anyone's guess as to what code to use as a benchmark for this question. \$\endgroup\$ Commented May 1, 2015 at 3:44
  • 2
    \$\begingroup\$ @NickAlexeev Yes, I agree, but it could have been made in a good answer, nonetheless (IMO). This is one of those cases where one could have spent a couple dozen of lines to explain the fact: a non-definitive answer (in this case) could be an answer, since it could point out why you cannot in general estimate the memory footprint of machine code generated by a C compiler without further information on the compiler, compiler options, actual C code, etc. I think it could be a useful reference and it doesn't fall in the "too broad" category. \$\endgroup\$ Commented May 1, 2015 at 10:54

2 Answers 2

11
\$\begingroup\$

Let's take some real world examples. I wrote a simple C program, which I think represents typical C code. Some could argue one way or another that it doesn't, but I think it will make my point.

Here is the C code:

unsigned short m [20];

int main()
{
    unsigned char a, x, i;
    unsigned short b, y;
    unsigned long c, z;

    a = b = c = 0;

    for (i=0; i < 20; i++)
    {
        a++;
        b++;
        c++;

        x = a * 3;
        y = b * 3;
        z = c * 3;

        if (a > 50)
        {
            a = 0;
        }

        m[i] = a / (b / (c - z) * x) + i;
    }
}

In addition to the 8-bit PIC18F asked about by the OP, I also compiled it for three other processors: an 8-bit 8051, an 8-bit PIC16F, and a 32-bit PIC32, and for each I took a look at the disassembly code to get the number of instructions and the number of bytes for each line of C code. Due to the length, I decided not to post the disassembly code here.

For the C code above, the PIC18F used 168 instructions and 336 bytes of code (all machine instructions were two bytes long). That however doesn't include some helper routines since the PIC18F for example doesn't have a hardware divide instruction, so a subroutine call is made for that. Of course these helper routines are shared for all the code in a program. So I'll ignore them since they probably affect the code size in a real program by a few percent.

The PIC16F used 272 instructions and 476 bytes of code (all machine instructions on the PIC16F are 14-bits long, so I converted this to bytes). Like the PIC18F, the PIC16F doesn't have a hardware divide instruction, so it also uses helper routines which were not included in the count.

The 8051 used 99 instructions and 175 bytes of code, or an average of 1.77 bytes per machine instruction. Like the PIC18F, the 8051 doesn't have a hardware divide instruction, so it also uses helper routines which were not included in the count.

The PIC32 used 68 instructions and 272 bytes of code. All machine instructions on the PIC32 take 4 bytes, unlike for example the 8051 where instructions can be variable length: 1, 2 or 3 bytes.

There are 11 lines of executable code in my C program. So that works out to be 15.2 instructions per line of C for the for the PIC18F; 24.7 instructions for the PIC16F; 9 instructions for the 8051; and 6.2 instructions For the PIC32.

As far as program bytes per line of code, the numbers are 30.5 bytes for the PIC18F; 43.3 bytes for the PIC16F; 15.9 bytes for the 8051; and 24.7 bytes for the PIC32. So the 8051 wins in terms of least number of bytes per line of C code.

However, for the three PIC compilers, I was not using the optimized versions (they have three versions of each compiler: free, standard, and pro). I was using the free one. Microchip claims the pro compilers can reduce code space by 60%. In my own work experience with the PIC32 pro compiler, I was getting 40-50% reduction. So I'm going to use 50% here as a compromise.

So the numbers become:

          Instructions/line of code    Bytes/line of code

PIC18F          7.6 (est)                  15.2 (est)                
PIC16F          12.4 (est)                 21.6 (est)
8051            9                          15.9
PIC32           3.1 (est)                  12.3 (est)

Interesting that the number of bytes per line of code is so similar between three of the processors, and not that much higher for the PIC16F.

So to answer the original question, for the PIC18F you get 1024/168 * 11 = 67.0 lines of C per 1K of code; for the PIC16F you can get 1024/272 * 11 = 41.4 lines of C, for the 8051 you can get 1024/175 * 11 = 64.4 lines of C, and for the PIC32, 1024/136 * 11 = 82.8 lines of C. So you get the most number of lines of C using the PIC32. I think the average number of lines of C (which is what the OP asked for) for most programs is probably somewhere between 25 and 120 lines of code depending on the processor and the program.

As far as lines of assembly instructions, for the PIC18F you can get 7.6 * 67.0 = 509 instructions; for the PIC16F you can get 12.3 * 40.4 * 16/14 = 567.9 instructions, for the 8051 you can get 9 * 62.8 = 565.2 instructions, and for the PIC32, 3.1 * 82.8 = 256.7

          Lines of C in 1K bytes    Instructions in 1K bytes

PIC18F          65.5 (est)               497.8 (est)                
PIC18F          40.4 (est)               567.9 (est)
8051            62.8                     565.2
PIC32           80.9 (est)               256.7 (est)

Note the "Instructions in 1K bytes" actually is just over 500 for the PIC18F, and 250 for the PIC32, since they use 2 and 4 bytes instruction respectively. The number for the PIC16F is higher due to the allowance for its 14-bit words.

\$\endgroup\$
4
  • \$\begingroup\$ What about optimization? Did you compile both with out it? \$\endgroup\$
    – Passerby
    Commented May 2, 2015 at 7:26
  • \$\begingroup\$ @Passerby I don't have the optimizing versions of these compilers at home, only at work (if I remember correctly, the optimized PIC32 compiler is around $800). From my experience there, the optimized code was about 40% smaller than the unoptimized. I'll include that in my answer. Thanks. \$\endgroup\$
    – tcrosley
    Commented May 2, 2015 at 8:01
  • \$\begingroup\$ "exactly 500". Not quite, since 1KB of memory on a uC is 1024B (they use the 2^10 system, not the 10^3 one). \$\endgroup\$ Commented May 2, 2015 at 15:04
  • \$\begingroup\$ @TomCarpenter I'll redo my calculations using 1024 instead of 1000. Thanks. \$\endgroup\$
    – tcrosley
    Commented May 2, 2015 at 16:46
8
\$\begingroup\$

As for C - it can be one line, or it can be a thousand. Depending on the constructs and optimization. For assembly it is clear - PIC18 has an instruction set composed of 16 and 32bit long instructions. So 1Kb can contain at 1024/2=512 instructions at most.

\$\endgroup\$
6
  • \$\begingroup\$ The OP didn't ask how many machine instructions in 1K of code, he asked for how many lines of C code. \$\endgroup\$
    – tcrosley
    Commented May 2, 2015 at 2:12
  • \$\begingroup\$ @tcrosley If you look carefully at the question you will notice the line about assembly that mostly translating one line to one instruction. So the answer is addressing both parts of the question. \$\endgroup\$
    – Eugene Sh.
    Commented May 2, 2015 at 2:16
  • 1
    \$\begingroup\$ Well, I disagree that on most processors, on average one line of C translates to one machine instruction. \$\endgroup\$
    – tcrosley
    Commented May 2, 2015 at 2:19
  • 4
    \$\begingroup\$ @tcrosley Do you mind re-reading the question and the answer? The answer is stating that you can't tell for C. But you can for assembly. \$\endgroup\$
    – Eugene Sh.
    Commented May 2, 2015 at 2:21
  • \$\begingroup\$ one line of c code can have several constants and several variable assiggments, there'n no way that's going to reduce to one istruction. \$\endgroup\$ Commented May 3, 2015 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.