аргументы вызова функции x64 push / mov order (MSVC) - PullRequest
0 голосов
/ 31 мая 2018

Я изучаю сборку x64 и использую базовый пример приложения с набором инструментов MS VC. Microsoft документирует , что первые 4 аргумента будут помещены в RC, RD, R8, R9 для целочисленных и указательных переменных, а остальные переменные будут использовать стек.Я понимаю это, и похоже на это из фрагмента кода, отладка сборки ниже, но я не могу понять, почему это не сделано по порядку?Я ожидал, что в разборке появятся толкающие аргументы справа налево в порядке e, d, c, b, a, cp, ip в приведенном ниже примере, но то, что я вижу, - это e, b, a и т. Д. Может кто-нибудь объяснить это??TIA

Фрагмент кода

__declspec(noinline) int testArgsAsm(int* x, char* cp, int a, int b, int c, int d, int e)
{
    std::cout << *x << *cp;
    int sum = a + b + c + d + e;
    if (sum == 0)
        std::cout << "0";
    else
        std::cout << "Non 0";
    return sum;

}
int main(int argc, const char** args)
{
    int a, b, c, d, e;
    int* ip = new int; *ip = 0x101;
    char* cp = new char; *cp = ('g');
    std::cin >> a >> b >> c >> d >> e;
    testArgsAsm(ip, cp, a,b,c,d,e);
    return 0;
}

Assembly

    testArgsAsm(ip, cp, a,b,c,d,e);
00007FF694DB1359  mov         eax,dword ptr [e]  
00007FF694DB135D  mov         r9d,dword ptr [b]  
00007FF694DB1362  mov         r8d,dword ptr [a]  
00007FF694DB1367  mov         dword ptr [rsp+30h],eax  
00007FF694DB136B  mov         eax,dword ptr [d]  
00007FF694DB136F  mov         dword ptr [rsp+28h],eax  
00007FF694DB1373  mov         eax,dword ptr [c]  
00007FF694DB1377  mov         rdx,rbx  
00007FF694DB137A  mov         rcx,rdi  
00007FF694DB137D  mov         dword ptr [rsp+20h],eax  
00007FF694DB1381  call        testArgsAsm (07FF694DB1270h)  <= Instruction pointer

registers at this instant
    RAX = 0000000000000003 RBX = 0000025633A16030 RCX = 0000025633A13EC0 RDX = 0000025633A16030
RSI = 0000000000000000 RDI = 0000025633A13EC0 R8  = 0000000000000001 R9  = 0000000000000002 
R10 = 000000000000000F R11 = 000000F5016F0001 R12 = 0000000000000000 R13 = 0000000000000000 
R14 = 0000000000000000 R15 = 0000000000000000 RIP = 00007FF694DB1381 RSP = 000000F5016FFB00 
RBP = 0000000000000000 EFL = 00000202 

PS: это может быть нубский вопрос, так как я только начинаю изучать asy

1 Ответ

0 голосов
/ 31 мая 2018

Я не могу понять, почему это не делается по порядку?

Все, что имеет значение, - это иметь правильные значения в правильных регистрах на call.Неважно, в каком порядке они там размещены.

Единственная причина, по которой нужно идти в обратном порядке с аргументами стека, - это когда вы используете push, чтобы выделить для них место в стеке одновременно схранить их.MSVC решает не делать этого, используя вместо этого mov, поэтому (кроме возможных различий в производительности) нулевая разница в том порядке, в котором аргументы записываются в память, если каждый из них записывается в нужное место.

Этот вызывающий объект уже зарезервировал пространство для аргументов + 32-байтовое пространство теней (где аргументы регистра могут быть переданы вызываемым пользователем для формирования массива аргументов, если он этого хочет), поэтому он использует mov вместо push.


Обычно функции сначала используют свои первые аргументы, поэтому установка его первой в вызывающей программе может избежать узкого места задержки и означает, что выполнение не по порядку не обязательнопосмотрите как далеко, чтобы найти инструкции, у которых готовые входные данные , когда внешний интерфейс начинает выдавать инструкции из вызываемой функции.(http://agner.org/optimize/).

Или просто, что компилятор анализировал аргументы функции слева направо и в конечном итоге выдавал asm, который шел в этом порядке.

...