I open my eyes. It’s pitch black. Panic sets as I prepare for the worst. I scream out for help but mid-scream a spotlight shines in to my eyes, temporarily blinding me. Instinctively, I raise my arm up to my face to block the light. As my eyes start to adjust to the light, I see the silhouette of a doll.
A few seconds go by, and the doll turns it’s head towards me and said in a french accent:
“ I want to play ze game... Iz i = i++ ze same aaaz i++? ”
Being a 1 month old software engineering student, I think back to all of my experience to try to answer the question.
That’s it, I lost.
I jolt up from my bed, with my phone alarm ringing in my ears. I swipe right turn off my alarm. Fully awake, I look up at the ceiling and recuperate my thoughts about my dream.
Does i = i++
increment i
then assigns the value to i
?
Something about the problem intrigued to dive deeper. So I leaped out of bed to my computer to get to the bottom of this enigma.
I put on some KPOP and started to write a simple test.
pretty self explanatory
My heart jumped a beat when the program ran.
i done messed up
Shit, you done messed up A-aron.
I had some time before I had to leave to go to school, so I decided to actually go even deeper and take a look at what exactly is going on in Assembly.
I opened up the test program executable with gdb and set a breakpoint at main so the program would run until main returns then stop.
(gdb) break main
Then I ran the program with this new breakpoint.
(gdb) run
Finally, I wanted to see the assembly instructions for the current function (main) so I used the disassemble
command.
(gdb) disassemble
That gave me this.
assembly for test program
Quick Assembly lesson.
Immediate values are constants and prefixed by a $
. Like $0xa
is the decimal 10 in hexadecimal. Register names are prefixed a %
.
Registers are small memory spaces in the processor of a computer that hold a single value. There are two types of registers: general registers and special registers. In our code sample, %eax
, %edx
, %esi
and %edi
are general registers, while %rbp
and %rsp
are special registers.
The first two lines are called the function preamble. This pushes the old base pointer onto the stack to save for later. Then it copies the value of the stack pointer to the base pointer. So after first two lines, %rbp
will point to the base of main’s stack frame.
Skipping down a few lines, we can see that the value $0xa
which is 10 in hexadecimal gets copied into -0x4(%rbp)
using the movl
instruction. movl
is the same as the mov
command but the l signifies that the operands will be a long
. -0x4(%rbp)
is the same as %rbp + -0x4
and because the stack grows downwards, subtracting 4 from the base of the current stack frame actually accesses the current frame itself. Thats were the local variable i
is stored. So $0xa
is being copied into the local variable i
.
The next line is where it gets interesting.
The lea
instruction is sort of like the mov
instruction. mov
, using syntax like mov <destination>, <source>
, moves the contents from the source to the destination.
lea
, however, moves the address of the source to the destination. It calculates the address specified by its second operand as if it were going to load or store data from it, but instead it stores the calculated address into the register specified by its first operand.
So the above instruction means %edx = %rax + 1
.
Then on the next line we see.
This moves the contents of -0x4(%rbp)
which is the local variable i
that has the value $0xa
into %edx
. So this operation is stored in a another temporary register, not the original register. So the increment was done, just in another temporary register.
Then I compared that to the second test of i++
.
This added $0x1
to i
.
This explains why i = i++
returns i
instead of i + 1
.
So the crux of the problem is a problem of evaluation order.
So when i = i++
is compiled:
i
gets copied to a temporary locationi
i
returns the temporary value, which is the same as the original valueHaving found the answer, I packed my things and got ready to go to school.
I arrived at school just in time for our Peer Learning Day.
I listened and participated as my peers started going over assignments from the previous week. Then out of nowhere I heard the question with the same french accent: