x64函数调用参数push / mov order(MSVC)

时间:2018-05-31 02:50:21

标签: c++ assembly visual-c++ x86-64 disassembly

我正在学习x64程序集和使用MS VC工具集的基本示例应用程序。 Microsoft documents前4个args将被推入RC,RD,R8,R9用于整数和指针变量,其余变量将使用堆栈。我理解,它看起来像是从代码片段,下面的汇编调试,但我无法理解为什么这些不是按顺序完成的?我期待反汇编在下面的示例中出现从右到左的顺序推送参数e,d,c,b,a,cp,ip,但我看到被推的是e,b,a等。 有人可以解释一下吗? TIA

代码段

public synchronized void clear() {
    // markers is the marker map
    for (Marker marker : markers.values()) {
        try {
            marker.remove();
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
    }

    // Clear all the marker map
    markers.clear();

    // Marker is the your global marker variable
    marker.remove();
}

PS:这可能是一个noob问题,因为我刚刚开始学习asy

1 个答案:

答案 0 :(得分:2)

  

我无法理解为什么这些没有按顺序完成?

重要的是在call的正确寄存器中输入正确的值。与他们在那里的顺序并不重要。

使用堆栈参数以相反顺序进行的唯一原因是当您使用push在存储它们的同时为它们分配堆栈空间时。 MSVC选择不这样做,而是使用mov,所以(除了可能的性能差异)它会使args写入内存的顺序为零,只要每个都被写入正确的位置。

这个调用者已经为args + 32字节阴影空间保留了空间(如果需要,寄存器args可以被调用者溢出以形成一个args数组),所以它使用{{1}而不是mov

首先使用第一个args的功能并不罕见,因此首先在调用者中设置它可能会避免延迟瓶颈并且意味着无序执行不必当前端开始从被调用函数发出指令时,看起来能够找到准备好输入的指令。 (http://agner.org/optimize/)。

或者只是编译器从左到右解析函数args并最终按顺序发出asm。