Carlton
Carlton

Reputation: 4297

Confused by this assembly code

I am trying to understand assembly a little better, so I've been paying attention to the assembly output from CDB when I debug my code. My platform is an Intel Xeon with Windows 7.

The following C++ code:

int main()
{
    int a = 30;
    int b = 0;
    b = ++a;
    return 0;
}

produces the following assembly for the line with the increment operator:

            b = ++a;
0x13f441023  <+0x0013>         mov     eax,dword ptr [rsp]
0x13f441026  <+0x0016>         inc     eax
0x13f441028  <+0x0018>         mov     dword ptr [rsp],eax  //Move eax to some memory address
0x13f44102b  <+0x001b>         mov     eax,dword ptr [rsp]  //Move it back to eax?
0x13f44102e  <+0x001e>         mov     dword ptr [rsp+4],eax

My question is, what is the purpose of moving the value in eax to memory, then immediately moving the same value back into eax, as indicated by the comments? Is this for thread safety, or just some artifact of a debug build?

Upvotes: 2

Views: 153

Answers (2)

Leeor
Leeor

Reputation: 19706

The compiler initially translates your instructions into assembly using static single assignment values (SSA), meaning that each operation gets a temporary value to store its result. Only at a later backend stage, these values would be translated into machine registers according to your target machine, and possibly into memory locations if necessary (explicitly required or spilled due to lack of registers).

Between these stages, the optimizer may eliminate partial values, but initially ++a is one operation, and assigning a (post increment) into b is a second operation. Since a and b are both local variables, they will be stored on the stack (and must be visible there, in case you step with a debugger for example), a will reside in [rsp] and b in [rsp+4].

So your compiler, at some point, probably has (in some intermediate representation):

    value1 = a
    value2 = value1 + 1
    a = value2  //self increment
    b = a

Or something similar. a and b must be memory resident, but the operations will usually be done on registers, so at first the compiler does -

    value1 = a
    value2 = value1 + 1
0x13f441023  <+0x0013>         mov     eax,dword ptr [rsp]
0x13f441026  <+0x0016>         inc     eax

    a = value2
0x13f441028  <+0x0018>         mov     dword ptr [rsp],eax

    b = a
0x13f44102b  <+0x001b>         mov     eax,dword ptr [rsp]
0x13f44102e  <+0x001e>         mov     dword ptr [rsp+4],eax 

Note that the intermediate values were kept in a register - in a normal compilation, they would have probably get eliminated altogether by one of the optimization passes (prior to register assignment and code generation).

Upvotes: 4

JSF
JSF

Reputation: 5321

just some artifact of a debug build?

Yes, just some artifact of a debug build (actually from an unoptimized build)

Upvotes: 0

Related Questions