为什么Console.WriteLine()使用ecx寄存器,即使eax和ebx是空闲的?

5

我正在研究CIL优化技术。我已经创建了这个简单的代码:

int Function() { return 10; }
// (...)
int Number = Function();
Console.WriteLine(Number);

当我在反汇编窗口观察这段代码时,我看到了如下内容:
00252DB0  mov ecx,0Ah  
00252DB5  call 63A96648  
00252DBA  ret  

我知道它将10放入ecx,然后使用63A96648作为指向WriteLine()函数的指针,但我不确定为什么要使用ecx寄存器。
我一直认为ecx主要用于循环计数器(嗯,它被称为“计数器寄存器”是有原因的...),我不确定为什么要在WriteLine()函数中使用它,即使eaxebx都是空闲的。即使我编写更复杂的函数,最终也总是在WriteLine()函数之前使用ecx
我尝试在互联网上查找关于它的任何信息,甚至在我大学图书馆里找了几本书,但我什么也没有找到。是ecx更快还是有任何理由使用它?
我完全意识到我不应该太在意它(因为只要它工作正常,我就没问题),但这个问题已经困扰我几天了,我希望有人能告诉我为什么要使用这个寄存器。

3
我怀疑它可能正在使用32位fastcall调用约定。 - Joachim Isaksson
1
看起来接近了但还差一点,它是__clrcall。 - Joachim Isaksson
1
通常情况下,这段代码(您的“Function”函数)不定义Console.WriteLine如何使用参数,因此它必须符合该方法所期望的(ecx中的参数)。 - 500 - Internal Server Error
1个回答

4

在x86架构中,使用__clrcall调用约定时,必须使用ECX寄存器。第一个参数(在此情况下为Number)通过ECX传递,如果有第二个参数,则通过EDX传递,其他参数则通过堆栈传递。

您还可以看到Function()方法被内联化,它完全消失了,优化器可以将其折叠成单个寄存器赋值。这是一种使属性与字段无法区分的优化技术。

这只适用于x86架构,如果允许其在64位模式下运行(删除Jitter forcing),则最多可以通过寄存器(rcx、rdx、r8和r9)传递4个参数。项目 > 属性 > 构建选项卡,平台目标 = AnyCPU,首选32位未选中。这应该是研究优化技术时要关注的代码类型。64位Jitter已经在VS2015中重写,项目名称为RyuJIT。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接