Last active
August 29, 2015 14:09
-
-
Save nikAizuddin/bf434b0388e1a3d4211f to your computer and use it in GitHub Desktop.
x + ++y - x * ++x - --y = -5 ? or = -6 ? Why = -6 ?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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