xorl %eax, %eax

Infinite Loops

with one comment

A couple of days ago someone on a IRC channel dedicated to C programming said something stupid.. He said: “which is faster? while(1) or for(;;)?“. I was sure that they were exactly the same but I decided to offer a more detailed approach. So, here it is! We have these two nice little proggies:

a.c:

#include <stdio.h>

int
main(void)
{
   char *str = "bleh";
   while (1)
      printf("%s\n", str);
   return 0;
}

b.c:

#include <stdio.h>

int
main(void)
{
   char *str = "bleh";
   for (;;)
      printf("%s\n", str);
   return 0;
}

And we compile both of them using GCC and the following options:

sh-3.1$ gcc a.c -O0 -std=c99 -pedantic -o a
sh-3.1$ gcc b.c -O0 -std=c99 -pedantic -o b
sh-3.1$

As you can see I have completely disabled the optimization features of GCC to have a natural interpretation with no extra fancy GCC stuff. Now, let’s have a look at the first disassembly using GDB:

0x08048354 <main+0>:    lea    0x4(%esp),%ecx
0x08048358 <main+4>:    and    $0xfffffff0,%esp
0x0804835b <main+7>:    pushl  0xfffffffc(%ecx)
0x0804835e <main+10>:   push   %ebp
0x0804835f <main+11>:   mov    %esp,%ebp
0x08048361 <main+13>:   push   %ecx
0x08048362 <main+14>:   sub    $0x14,%esp
0x08048365 <main+17>:   movl   $0x8048488,0xfffffff8(%ebp)
0x0804836c <main+24>:   mov    0xfffffff8(%ebp),%eax
0x0804836f <main+27>:   mov    %eax,(%esp)
0x08048372 <main+30>:   call   0x804827c <puts@plt>
0x08048377 <main+35>:   jmp    0x804836c <main+24>
0x08048379 <main+37>:   nop
0x0804837a <main+38>:   nop
0x0804837b <main+39>:   nop
0x0804837c <main+40>:   nop
0x0804837d <main+41>:   nop
0x0804837e <main+42>:   nop
0x0804837f <main+43>:   nop
End of assembler dump.

Nothing exciting, the while loop is a simple JMP instruction. Here is the commented code for the infinite loop:

<main+24>:   mov    0xfffffff8(%ebp),%eax   ; Put str to EAX
<main+27>:   mov    %eax,(%esp)             ; Put EAX on the location of ESP (stack)
<main+30>:   call   0x804827c <puts@plt>    ; Call puts() to print str
<main+35>:   jmp    0x804836c <main+24>     ; Jump to main+24

Exactly as you might be thinking of it. Now, let’s move to the for loop which I expect to be the same. Let’s see…

0x08048354 <main+0>:    lea    0x4(%esp),%ecx
0x08048358 <main+4>:    and    $0xfffffff0,%esp
0x0804835b <main+7>:    pushl  0xfffffffc(%ecx)
0x0804835e <main+10>:   push   %ebp
0x0804835f <main+11>:   mov    %esp,%ebp
0x08048361 <main+13>:   push   %ecx
0x08048362 <main+14>:   sub    $0x14,%esp
0x08048365 <main+17>:   movl   $0x8048488,0xfffffff8(%ebp)
0x0804836c <main+24>:   mov    0xfffffff8(%ebp),%eax
0x0804836f <main+27>:   mov    %eax,(%esp)
0x08048372 <main+30>:   call   0x804827c <puts@plt>
0x08048377 <main+35>:   jmp    0x804836c <main+24>
0x08048379 <main+37>:   nop
0x0804837a <main+38>:   nop
0x0804837b <main+39>:   nop
0x0804837c <main+40>:   nop
0x0804837d <main+41>:   nop
0x0804837e <main+42>:   nop
0x0804837f <main+43>:   nop
End of assembler dump.

Obviously it’s exactly the same! Try it on your own and you’ll that it’s the same. Most C programmers will already know this but I have to sacrifice a post and publish this in reply to some people that don’t believe it. You know.., It’s awful when someone is wrong on the internet ;p

Written by xorl

January 27, 2009 at 13:30

Posted in C programming

One Response

Subscribe to comments with RSS.

  1. Bjarne Stroustrup wrote about it in his cpp book.
    But you demonstrated! Good work.

    nawhcs

    October 19, 2010 at 17:47


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s