x86 程序集比较参数

x86 Assembly Compare Arguments

本文关键字:参数 比较 程序集 x86      更新时间:2023-10-16

我正在使用Visual Studio并从C++调用汇编。我知道当您将参数传递给程序集时,第一个参数在 ECX 中,第二个参数在 EDX 中。为什么我不能在不先将 ECX 复制到 EAX 的情况下直接比较两个寄存器?

C++:

#include <iostream>
extern "C" int PassingParameters(int a, int b);
int main()
{
    std::cout << "The function returned: " << PassingParameters(5, 10) << std::endl;
    std::cin.get();
    return 0;
}

ASM:在直接比较两个寄存器时,这会给出错误的值。

.code
PassingParameters proc
    cmp edx, ecx
    jg ReturnEAX
    mov eax, edx
ReturnEAX:
    ret
PassingParameters endp
end

但是如果我这样写,我得到正确的值,并且可以直接比较两个寄存器,这是为什么呢?

.code
PassingParameters proc
    mov eax, ecx ; copy ecx to eax.
    cmp edx, ecx ; compare ecx and edx directly like above, but this gives the correct value.
    jg ReturnEAX
    mov eax, edx
ReturnEAX:
    ret
PassingParameters endp
end

在你的第一个版本中,如果jg被采用,你离开eax时完全像进入函数时一样(即,我们几乎不知道)。由于返回值通常以 eax 为单位,因此每当采用jg时,都会给出未定义的返回。换句话说,你写的东西大致是这样的:

int PassingParameters(int a, int b) { 
    if (a < b)
        return a;
}

在这种情况下,如果a==ba>b,则返回值为垃圾。

在第二个代码序列中,您将一个值加载到 eax 中。然后,如果没有采用 jg,您将其他值加载到 eax 中。无论哪种方式,返回值都将是一个输入参数或另一个输入参数(取决于哪个更大)。换句话说,您拥有的大致相当于:

int PassingParameters(int a, int b) { 
   if (a<b)
       return a;
    return b;
}

附言我还要指出,您的代码看起来像 x86,而不是 64 位代码。对于 64 位代码,您应该使用 RAX、RCX 等,而不是 EAX、ECX 等。