c++ - 对这段汇编代码感到困惑

标签 c++ assembly

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

以下 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 中,如注释所示,目的是什么?这是为了线程安全,还是只是调试构建的一些工件?

最佳答案

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

在这些阶段之间,优化器可能会消除部分值,但最初++a 是一个操作,将 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 

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

关于c++ - 对这段汇编代码感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32051085/

相关文章:

c++ - 如何在 C++ 和 Visual Studio 2008 中使用 asm 代码

c++ - 随机数生成器的问题

C++ 自动矢量化矩阵乘法循环

c++ - C++ wrt 字符串中的 STL 排序函数

C++ cin一直在跳

assembly - 汇编仅在软件中实现吗?

c++ - 优化在网格图中查找哈密顿循环的函数?

assembly - 将 XMM 寄存器压入堆栈

c++ - 是否可以在 C++17 的 GCC 中使用显式寄存器变量?

c - ARM汇编递归幂函数