这个汇编代码

时间:2015-08-17 12:59:10

标签: c++ assembly

我试图更好地理解汇编,所以当我调试代码时,我一直在关注CDB的汇编输出。我的平台是带有Windows 7的Intel Xeon。

以下C ++代码:

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

使用增量运算符为行生成以下程序集:

            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

我的问题是,将eax中的值移动到内存中的目的是什么,然后立即将相同的值移回eax,如注释所示?这是为了线程安全,还是只是调试构建的一些工件?

2 个答案:

答案 0 :(得分:4)

编译器最初使用static single assignment值(SSA)将指令转换为汇编,这意味着每个操作都会获得一个临时值来存储其结果。只有在后期的后端阶段,这些值才会根据您的目标机器转换为机器寄存器,如果需要,可能会转换为内存位置(由于缺少寄存器而明确要求或溢出)。

在这些阶段之间,优化器可以消除部分值,但最初++ a是一个操作,并且将(后增量)分配给b是第二个操作。由于a和b都是局部变量,它们将存储在堆栈中(并且必须在那里可见,以防你以调试器为例),a将驻留在[rsp]中,b驻留在[rsp + 4]中。

所以你的编译器在某些时候可能(在某些中间表示中):

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

或类似的东西。 a和b必须是驻留内存,但操作通常是在寄存器上完成的,所以首先编译器会这样做 -

    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 

请注意,中间值保存在寄存器中 - 在正常编译中,它们可能会通过其中一个优化过程(在寄存器分配和代码生成之前)完全消除。

答案 1 :(得分:0)

  

只是调试版本的一些工件?

是的,只是调试版本的一些工件(实际上来自未经优化的版本)