side effect of “++” in C – compiler implemenation with assembly

This post shows a common known side effect of “++” operator in C programming because of different compiler implementation. Assembly code from PowerPC and x86 with gcc is provide to show the key difference and the reason why for this side effect. Detailed comments may not be completely correct. However, should be easy to get the point:)

/* sideEffect1.c */

#include <stdio.h>

int main()
{
        int n = 0;
        printf(“n1 = %d, n2 = %dn”, n++, n++);
        return 0;
}

/* PowerPC */

/loads/umts6/cpsb/montavista/M8cge4.0_drop090305/montavista/cge/devkit/ppc/7xx/bin/ppc_7xx-gcc -v
Reading specs from /loads/umts6/cpsb/montavista/M8cge4.0_drop090305/montavista/cge/devkit/ppc/7xx/bin/../lib/gcc/powerpc-montavista-linux/3.4.3/specs
Configured with: ../configure –host=i686-pc-linux-gnu –target=powerpc-montavista-linux –prefix=/opt/montavista/foundation/devkit/ppc/7xx –exec-prefix=/opt/montavista/foundation/devkit/ppc/7xx –bindir=/opt/montavista/foundation/devkit/ppc/7xx/bin –sbindir=/opt/montavista/foundation/devkit/ppc/7xx/sbin –sysconfdir=/opt/montavista/foundation/devkit/ppc/7xx/etc –datadir=/opt/montavista/foundation/devkit/ppc/7xx/share –includedir=/opt/montavista/foundation/devkit/ppc/7xx/include –libdir=/opt/montavista/foundation/devkit/ppc/7xx/lib –libexecdir=/opt/montavista/foundation/devkit/ppc/7xx/libexec –localstatedir=/opt/montavista/foundation/devkit/ppc/7xx/var –sharedstatedir=/opt/montavista/foundation/devkit/ppc/7xx/share –mandir=/opt/montavista/foundation/devkit/ppc/7xx/man –infodir=/opt/montavista/foundation/devkit/ppc/7xx/info –build=i686-pc-linux-gnu –program-transform-name=s,^,ppc_7xx-, –enable-cross –with-sysroot=/opt/montavista/foundation/devkit/ppc/7xx/target !
 –enable-shared –enable-languages=c,c++ –enable-__cxa_atexit –enable-threads=posix –disable-multilib –with-gxx-include-dir=${prefix}/lib/gcc/powerpc-montavista-linux/3.4.3/../../../../target/usr/include/c++/3.4.3 –with-numa-policy=no –with-cpu=750 –libexecdir=/opt/montavista/foundation/devkit/ppc/7xx/lib
Thread model: posix
gcc version 3.4.3 (MontaVista 3.4.3-25.0.145.0801204 2008-06-04)

<dv111-s01c10h0:lss>/export/home/lss:
# uname -a
Linux dv111-s01c10h0 2.6.10_mvlcge401-katana #2403 Fri Jan 20 10:25:01 CST 2012 ppc
<dv111-s01c10h0:lss>/export/home/lss:
# ./sideEffect1
n1 = 0, n2 = 1
<dv111-s01c10h0:lss>/export/home/lss:

1000028c <main>:
#include <stdio.h>

int main()
{
1000028c:       94 21 ff e0     stwu    r1,-32(r1)      /* store stack pointer to r1-32 and update r1=r1-32 */
10000290:       7c 08 02 a6     mflr    r0              /* get link register – set up the stack frame */
10000294:       93 e1 00 1c     stw     r31,28(r1)      /* store nonvolatile r31 to 28(r1) */
10000298:       90 01 00 24     stw     r0,36(r1)       /* store old link register to 36(r1) */
1000029c:       7c 3f 0b 78     mr      r31,r1          /* move stack pointer to r31 */
        int n = 0;
100002a0:       38 00 00 00     li      r0,0            /* load 0 to r0 */
100002a4:       90 1f 00 08     stw     r0,8(r31)       /* store r0(0) to 8(r31)=8(r1), (n=0, 8(r31))*/
        printf(“n1 = %d, n2 = %dn”, n++, n++);
100002a8:       81 3f 00 08     lwz     r9,8(r31)       /* load 8(r31) to r9 */
100002ac:       7d 20 4b 78     mr      r0,r9           /* move r9 to r0(0) */
100002b0:       39 29 00 01     addi    r9,r9,1         /* r9=r9+1, (n++, r9(1)) */
100002b4:       91 3f 00 08     stw     r9,8(r31)       /* store r9 to 8(r31), (n=1, 8(r31)) */
100002b8:       81 3f 00 08     lwz     r9,8(r31)       /* load 8(r31) to r9(1) again */
100002bc:       7d 2b 4b 78     mr      r11,r9          /* move r9 to r11(1) */
100002c0:       39 29 00 01     addi    r9,r9,1         /* r9=r9+1, (n++, r9(2)) */
100002c4:       91 3f 00 08     stw     r9,8(r31)       /* store r9 to 8(r31), (n=2, 8(r31)) */
100002c8:       3d 20 10 05     lis     r9,4101         /* load 4101 to r9 */
100002cc:       38 69 4c ac     addi    r3,r9,19628     /* r3=r9+19628=4101+19628=23729 – first parameter */
100002d0:       7c 04 03 78     mr      r4,r0           /* move r0 to r4(0) – second parameter */
100002d4:       7d 65 5b 78     mr      r5,r11          /* move r11 to r5(1) – third parameter */
100002d8:       4c c6 31 82     crclr   4*cr1+eq        /* clear the control register */
100002dc:       48 00 0b 59     bl      10000e34 <_IO_printf>   /* printf(“…”, 0, 1); */
        return 0;
100002e0:       38 00 00 00     li      r0,0            /* load 0 to r0(0) */
}
100002e4:       7c 03 03 78     mr      r3,r0           /* move r0 to r3(0) */
100002e8:       81 61 00 00     lwz     r11,0(r1)       /* load saved link register (in printf) to r11 */
100002ec:       80 0b 00 04     lwz     r0,4(r11)       /* load next link register (saved in main) to r0 */
100002f0:       7c 08 03 a6     mtlr    r0              /* set link register to r0 – recover link register */
100002f4:       83 eb ff fc     lwz     r31,-4(r11)     /* load -4(r11) (original saved in 28(r1)) back to nonvolatile r31 */
100002f8:       7d 61 5b 78     mr      r1,r11          /* move saved link register to stack pointer */
100002fc:       4e 80 00 20     blr                     /* exit */

/* x86 */

/home/daveti/Ctest/sideEffect/x86: uname -a
Linux lssxlinux1.ih.lucent.com 2.6.32-042stab044.11 #1 SMP Wed Dec 14 16:02:00 MSK 2011 i686
/home/daveti/Ctest/sideEffect/x86: gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
Configured with: ../configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –enable-shared –enable-threads=posix –disable-checking –with-system-zlib –enable-__cxa_atexit –host=i386-redhat-linux
Thread model: posix
gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
/home/daveti/Ctest/sideEffect/x86: ./sideEffect1
n1 = 1, n2 = 0
/home/daveti/Ctest/sideEffect/x86:

080481d0 <main>:
#include <stdio.h>

int main()
{
 80481d0:       55                      push   %ebp
 80481d1:       89 e5                   mov    %esp,%ebp                /* save and update ebp */
 80481d3:       83 ec 08                sub    $0x8,%esp                /* ‘grow’ 8 bytes in the stack */
 80481d6:       83 e4 f0                and    $0xfffffff0,%esp         /* 16-byte alignment for the stack */
 80481d9:       b8 00 00 00 00          mov    $0x0,%eax
 80481de:       29 c4                   sub    %eax,%esp
        int n = 0;
 80481e0:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)    /* n=0, -4(%ebp) */
        printf(“n1 = %d, n2 = %dn”, n++, n++);
 80481e7:       83 ec 04                sub    $0x4,%esp                /* ‘grow’ 4 bytes in the stack */
 80481ea:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
 80481ed:       50                      push   %eax                     /* push n=0 – last parameter */
 80481ee:       8d 45 fc                lea    0xfffffffc(%ebp),%eax
 80481f1:       ff 00                   incl   (%eax)                   /* n++; (n=1)*/
 80481f3:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
 80481f6:       50                      push   %eax                     /* push n=1 – second parameter */
 80481f7:       8d 45 fc                lea    0xfffffffc(%ebp),%eax
 80481fa:       ff 00                   incl   (%eax)                   /* n++; (n=2) */
 80481fc:       68 c8 f7 08 08          push   $0x808f7c8               /* push “format string” – first paramter */
 8048201:       e8 b2 06 00 00          call   80488b8 <_IO_printf>     /* printf(“…”, 1, 0); */
 8048206:       83 c4 10                add    $0x10,%esp               /* ‘degrow’ 16 bytes in the stack */
        return 0;
 8048209:       b8 00 00 00 00          mov    $0x0,%eax
}
 804820e:       c9                      leave
 804820f:       c3                      ret

About daveti

Interested in kernel hacking, compilers, machine learning and guitars.
This entry was posted in Programming, Stuff about Compiler and tagged , , , . Bookmark the permalink.

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