为什么函数调用会将其第一个参数放入 CPU 寄存器 RDX?

问题描述

当我逐步浏览我的一个库中的一些新代码时,我注意到第一个参数似乎进入 RDX 寄存器而不是记录的 RCX 寄存器。虽然不是世界末日的灾难,但我很好奇;为什么会这样,除非 RCX 被搁置以传递对 this 的引用,就像在 C++ 中发生的那样。同样,被调用的例程是实例上的静态方法可能也很重要。

以下是对整个函数的反汇编,这是一个非常基础的语法糖函数

        /// </summary>
        /// <param name="pasTradditionalMessages">
        /// Pass in the optional list of additonal messages if needed. Status
        /// codes zero and one are covered by stanard messages that are pulled
        /// from the resource strings stored in WizardWrx.Common.dll.
        /// </param>
        /// <returns>
        /// The total number of messages is as described under <paramref name="pasTradditionalMessages"/>.
        /// </returns>
        private static int ComputeMessageCount ( string [ ] pasTradditionalMessages )
        {
00007FFED9688940  push        rbp  
00007FFED9688941  push        rdi  
00007FFED9688942  push        rsi  
00007FFED9688943  sub         rsp,30h  
00007FFED9688947  mov         rbp,rsp  
00007FFED968894A  mov         rsi,rcx  
00007FFED968894D  lea         rdi,[rbp+20h]  
00007FFED9688951  mov         ecx,4  
00007FFED9688956  xor         eax,eax  
00007FFED9688958  rep stos    dword ptr [rdi]  
00007FFED968895A  mov         rcx,rsi  
00007FFED968895D  mov         qword ptr [rbp+50h],rcx  
00007FFED9688961  cmp         dword ptr [7FFED95791F8h],0  
00007FFED9688968  je          WizardWrx.ConsoleAppAids3.ConsoleAppStateManager.ComputeMessageCount(System.String[])+02Fh (07FFED968896Fh)  
00007FFED968896A  call        00007FFF390CCBA0  
00007FFED968896F  nop  
            return pasTradditionalMessages == null ? STANDARD_MESSAGE_COUNT : pasTradditionalMessages.Length + STANDARD_MESSAGE_COUNT;
00007FFED9688970  cmp         qword ptr [rbp+50h],0  
00007FFED9688975  je          WizardWrx.ConsoleAppAids3.ConsoleAppStateManager.ComputeMessageCount(System.String[])+046h (07FFED9688986h)  
00007FFED9688977  mov         rax,qword ptr [rbp+50h]  
00007FFED968897B  mov         eax,dword ptr [rax+8]  
00007FFED968897E  add         eax,2  
00007FFED9688981  mov         dword ptr [rbp+20h],eax  
00007FFED9688984  jmp         WizardWrx.ConsoleAppAids3.ConsoleAppStateManager.ComputeMessageCount(System.String[])+04Dh (07FFED968898Dh)  
00007FFED9688986  mov         dword ptr [rbp+20h],2  
00007FFED968898D  mov         eax,dword ptr [rbp+20h]  
00007FFED9688990  mov         dword ptr [rbp+24h],eax  
00007FFED9688993  nop  
00007FFED9688994  jmp         WizardWrx.ConsoleAppAids3.ConsoleAppStateManager.ComputeMessageCount(System.String[])+056h (07FFED9688996h)  
        }   // private static int ComputeMessageCount
00007FFED9688996  mov         eax,dword ptr [rbp+24h]  
00007FFED9688999  lea         rsp,[rbp+30h]  
00007FFED968899D  pop         rsi  
00007FFED968899E  pop         rdi  
00007FFED968899F  pop         rbp  
00007FFED96889A0  ret  

解决方法

这不是你想的那样 - 在序言中:

00007FFED9688940  push        rbp       // SAVE RBP
00007FFED9688941  push        rdi       // SAVE RDI
00007FFED9688942  push        rsi       // SAVING RSI
00007FFED9688943  sub         rsp,30h   // ADD STACK SPACE
00007FFED9688947  mov         rbp,rsp   // SAVE STACK POINTER
00007FFED968894A  mov         rsi,rcx   // SAVING RCX - (Already contains your string[] argument)
00007FFED968894D  lea         rdi,[rbp+20h]  
00007FFED9688951  mov         ecx,4  
00007FFED9688956  xor         eax,eax  
00007FFED9688958  rep stos    dword ptr [rdi]  // STACK OPS ^^^
00007FFED968895A  mov         rcx,rsi  // *****  HERE Moving string[] back to RCX in preparation for the call
00007FFED968895D  mov         qword ptr [rbp+50h],rcx  
00007FFED9688961  cmp         dword ptr [7FFED95791F8h],0  
00007FFED9688968  je          WizardWrx.ConsoleAppAids3.ConsoleAppStateManager.ComputeMessageCount(System.String[])+02Fh (07FFED968896Fh)  
00007FFED968896A  call        00007FFF390CCBA0  

在调用该函数之前,您的字符串数组似乎已经存在于 RCX 中。在方法调用之前,调用者保存 RBP、RDI 和 RSI,然后添加堆栈空间并将其当前 RCX 指针保存到 RSI(函数返回后会弹出)。

接下来是一些堆栈操作,然后为调用设置参数 - 只有一个,所以 mov rcx,rsi - 正如预期的那样,您的数组指针将进入 RCX。 RDX 在这个反汇编中没有出现。