Почему MS FastCall на x86 не использует EAX в качестве первого аргумента?

Согласно википедии: "Соглашение Microsoft или GCC __fastcall (также известное как __msfastcall) передает первые два аргумента (оцениваются слева направо), которые соответствуют ECX и EDX. Остальные аргументы помещаются в стек справа налево".

Почему они решили не использовать EAX, ECX, EDX для arg0, arg1, arg2? Если они собираются вставить аргументы в регистры, зачем останавливаться на 2? Я знаю, что быстро Borland все это делает, поэтому Microsoft решила не использовать EAX, просто чтобы быть другим?

1 ответ

Из-за ограничений набора команд x86, нет
Звоните немедленно
команда есть
CALL IP.offset,
который является относительным. Конечно, разработчики компиляторов хотели бы зарезервировать что-либо с абсолютным смещением, и производители процессоров могли бы сделать это, поэтому у нас есть следующий "компромисс":
MOV eax, absolute_address (метка)
CALL Eax
который был бы равен
CALL absolute_address(метка)
Такой метод вызова потребовал бы 1 временный регистр, только для вызова, который можно легко использовать повторно, и EAX - лучший вариант для этой цели.
Результат таких соображений полезен, и вы можете использовать его в своем ассемблерном коде. Тесты показывают, что предикторы ветвления будут, по крайней мере частично, правильно работать с таким кодом. Другая возможность, но редкая, это когда вам нужно сбросить флаги, чтобы избежать потери зависимости или частичного останова регистра при вызове процедуры, которая уже находится в кеше верхнего уровня. Это может произойти, например, если вы используете что-то вроде mov ah, 1 в самом начале вашей подпрограммы. Чтобы избежать этого, используйте EAX в качестве временного регистра и введите
XOR eax, eax
непосредственно перед звонком. Это может на самом деле сохранить несколько тактов в некоторых редких случаях. Но реальная выгода от этого по сравнению с использованием его для передачи параметров сомнительна, и причины этого могут быть такими, как указано выше.

Другие вопросы по тегам