被这个汇编代码弄糊涂了

Confused by this assembly code

本文关键字:弄糊涂 代码 汇编      更新时间:2023-10-16

我试图更好地理解汇编,所以当我调试代码时,我一直在关注CDB的汇编输出。我的平台是搭载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,如注释所示?这是为了线程安全,还是只是调试构建的一些工件?

编译器最初使用静态单赋值(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 

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

只是调试构建的一些工件?

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