Here's the disassembly of main (the part we need):
0x080483ed <+9>: movl $0xa,0x1c(%esp) # initializes i
0x080483f5 <+17>: addl $0x1,0x1c(%esp) # i += 1
0x080483fa <+22>: mov 0x1c(%esp),%edx # edx = i = 11
0x080483fe <+26>: addl $0x1,0x1c(%esp) # i += 1
0x08048403 <+31>: mov $0x80484f0,%eax # address of string
0x08048408 <+36>: mov 0x1c(%esp),%ecx # ecx = i = 12
0x0804840c <+40>: mov %ecx,0xc(%esp) # pushes ecx (++i)
0x08048410 <+44>: mov %edx,0x8(%esp) # and edx (i++)
0x08048414 <+48>: mov 0x1c(%esp),%edx # now gets edx (i)
0x08048418 <+52>: mov %edx,0x4(%esp) # and pushes it
0x0804841c <+56>: mov %eax,(%esp) # push address of string
0x0804841f <+59>: call 0x804831c <printf@plt> # write
now, since arguments are pushed on the stack in reverse order, the disassembly shows that the first that is pushed is ecx, so we can assume it's ++i (since it's the last argument in printf), so edx is i++. Strangely, it decides to compute first i++, then ++i. At the end it loads i and pushes it, but, at this point, i has been increased two times, so it's 12.
This is really undefined behavior! Look:
printf("++i=%d\ni++=%d\ni=%d\n",++i,i++,i);
produces:
++i=12
i++=10
i=12