Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nikAizuddin/bf434b0388e1a3d4211f to your computer and use it in GitHub Desktop.
Save nikAizuddin/bf434b0388e1a3d4211f to your computer and use it in GitHub Desktop.
x + ++y - x * ++x - --y = -5 ? or = -6 ? Why = -6 ?
How the GNU GCC compiler calculate the equation:
x + ++y - x * ++x - --y
The algorithm used when perform this computation may be different across
compilers. This program is compiled using compiler GNU GCC 4.8.3 built for
Red Hat 4.8.3-7. Tools that are used to reverse engineer or disassemble
this program are "objdump" and "GNU GDB debugger".
The program will solve the following problem:
x + ++y - x * ++x - --y
Given:
x = 2
y = 3
So, we write the C program code to solve this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int x = 2;
int y = 3;
int z = 0;
z = x + ++y - x * ++x - --y;
printf("z = %d\n",z);
return 0;
}
However, the way this program calculates is not as we expected.
The observation below is based on disassembling the program.
The step-by-step instruction that is performed by the program:
--------------------------------------------------------------
Problem: x + ++y - x * ++x - --y
Given: x = 2, y = 3
STEP 1:
(x + ++y) - x * ++x - --y
y = y + 1
y = 3 + 1
y = 4
(2 + 4) -x * ++x - --y
6 - x * ++x - --y
STEP 2:
6 - (x * ++x) - --y
x = x + 1
x = 2 + 1
x = 3
6 - (3 * 3) - --y
6 - 9 - --y
STEP 3:
(6 - 9) - --y
-3 - --y
STEP 4:
(-3 - --y)
y = y - 1
y = 4 - 1
y = 3
-3 - 3
-6
From this observation, we see that the program first perform (x + ++y)
instead of (x * ++x). To prove this, here the results when disassemble
the program.
NOTES: "..." = instruction that is not important
08048420 <main>:
...
...
...
sub $0x20,%esp ;reserve 32 bytes of stack for var x, y, and z
movl $0x2,0x1c(%esp) ;int x = 2
...
movl $0x3,0x18(%esp) ;int y = 3
...
movl $0x0,0x14(%esp) ;int z = 0
...
addl $0x1,0x18(%esp) ;y = y + 1
mov 0x1c(%esp),%eax ;eax = x
mov 0x18(%esp),%edx ;edx = y
add %eax,%edx ;edx = edx + eax
addl $0x1,0x1c(%esp) ;x = x + 1
mov 0x1c(%esp),%eax ;eax = x
imul 0x1c(%esp),%eax ;eax = eax * x
sub %eax,%edx ;edx = edx - eax
mov %edx,%eax ;eax = edx
subl $0x1,0x18(%esp) ;y = y - 1
sub 0x18(%esp),%eax ;eax = eax - y
mov %eax,0x14(%esp) ;z = eax
...
...
...
call 80482f0 <printf@plt> ;printf()
mov $0x0,%eax ;return 0
leave
ret
...
...
...
The list below shows the stack memory usage in function int main(void)
+0: <empty>
+1: <empty>
+2: <empty>
+3: <empty>
+4: <empty>
+5: <empty>
+6: <empty>
+7: <empty>
+8: <empty>
+9: <empty>
+10: <empty>
+11: <empty>
+12: <empty>
+13: <empty>
+14: <empty>
+15: <empty>
+16: <empty>
+17: <empty>
+18: <empty>
+19: <empty>
+20: z = 0 ---- 0x14(%esp) [bit 0 -> bit 7 ]
+21: z = 0 ---- 0x14(%esp) [bit 8 -> bit 15]
+22: z = 0 ---- 0x14(%esp) [bit 16 -> bit 23]
+23: z = 0 ---- 0x14(%esp) [bit 24 -> bit 31]
+24: y = 3 ---- 0x18(%esp) [bit 0 -> bit 7 ]
+25: y = 3 ---- 0x18(%esp) [bit 8 -> bit 15]
+26: y = 3 ---- 0x18(%esp) [bit 16 -> bit 23]
+27: y = 3 ---- 0x18(%esp) [bit 24 -> bit 31]
+28: x = 2 ---- 0x1c(%esp) [bit 0 -> bit 7 ]
+29: x = 2 ---- 0x1c(%esp) [bit 8 -> bit 15]
+30: x = 2 ---- 0x1c(%esp) [bit 16 -> bit 23]
+31: x = 2 ---- 0x1c(%esp) [bit 24 -> bit 31]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment