Вы бы порекомендовали использовать сборку для доступа к аргументам в этом исключительном случае?

рассмотрим следующую функцию, которая не будет встроена, и примем x86 в качестве платформы:

void doSomething(int & in){
//do something
}

во-первых, я не уверен, что такой сценарий произойдет, но, поскольку я думаю, что это возможно, я спрошу, так что ЕСЛИ в любом вызывающем объекте эта функция вызывается, то передаваемый аргумент находится точно в верхней части фрейма стека вызывающего, так что в доступ к вызываемой функции к этому через регистр ebp (после того, как вызываемый объект переместил содержимое esp в ebp) на языке ассемблера возможен, вы предлагаете вообще игнорировать объявление параметра для функции и использовать ассемблер для доступа к нашим аргументам в этом исключительном случае или просто оставить определение функции как есть и оставить компилятору делать то, что он делает? поскольку я нигде не читал, этот компилятор рассматривал бы такой исключительный случай как фактор для соглашения о вызовах, и я думаю, что он просто сгенерирует код для передачи указателя на аргумент в фрейм стека вызываемого или в один из регистров

0

Решение

Прежде всего, это так легко сломать — например, вы получаете другую версию компилятора, которая генерирует код по-разному. Или вы меняете функции оптимизации. Не берите в голову ситуацию, когда вам вдруг нужно использовать doSomething в другом месте, и тогда это не будет работать, потому что переменная больше не находится на вершине стека.

Во-вторых, если предположить, что код внутри функции достаточно короткий, весьма вероятно, что компилятор встроит функцию, так что вы вообще ничего не «потеряете».

В-третьих, единственный аргумент в современных компиляторах, как правило, в любом случае передается в регистр, поэтому при включенной оптимизации это не дает никаких преимуществ.

Если вы действительно считаете, что в этом есть какая-то полезная выгода, и компилятор не встроит или не оптимизирует код иным образом [вы смотрели на сгенерированный код?], Тогда попробуйте использовать forceinline или же always_inline или как там это называется в вашем компиляторе (у большинства компиляторов есть такая опция). Если это не сработает, используйте макрос, чтобы вставить его вручную. Или просто переместите код туда, где он называется «copy-n-paste».

4

Другие решения

Ваша заметкапередаваемый аргумент находится точно в верхней части фрейма стека вызывающего, так что в вызываемой функции доступ к нему осуществляется через регистр ebp«содержит фактическое недоразумение.

Это из-за следующих вещей:

  • вы предполагаете соглашение о вызовах на основе стека, т.е. pushперед вызовом в стек callв функции. Это обычно не так; даже на 32-битной платформе x86 существуют соглашения о вызовах, не основанных на стеке (например, Windows fastcall или GNU GCC, используемые в 32-битном ядре Linux). Если таковые используются, аргумент не будет найден в верхней части стека, а скорее … в любом регистре, который используется для хранения первого аргумента.

    Но даже если у вас есть передача параметров на основе стека … все же:

  • вы пропустили это на x86 по крайней мере call инструкция толкает обратный адрес на вершину стека, так что, когда первая инструкция функции достигла этого пути, выполняется, ESP будет указывать не на первый аргумент этой функции, а на обратный адрес.
  • ты пропустил это EBP регистры, сохраненные вызываемым пользователем (сохраняются через вызовы функций) и не инициализируются архитектурой от вашего имени — необходимо, чтобы сгенерированный код эксплицитно настроить это. Поэтому функция, которая хочет использовать его (даже если только как указатель кадра), обязана сохранить его где-то перед использованием. Это означает, что нормальный пролог буду иметь push EBP; mov EBP, ESP (ты не можешь только делать MOV EBP, ESP потому что это было бы затирать вызывающий EBP который недействителен / что вы не можете сделать). Поэтому, если вы хотите сослаться на первый аргумент функции, вам нужно [ EBP + 8 ] не [ EBP ],
    Если вы не используя framepointers, затем первый аргумент (из-за call который был использован для достижения функции, нажав адрес возврата) находится в [ ESP + 4 ] не [ ESP ],

Я надеюсь, что это проясняет немного.

Я согласен с другими постерами, что прояснение вопроса поможет, чего именно вы хотите достичь и почему, по вашему мнению, язык ассемблера может быть полезен здесь.

2

Нет, я не буду. Соглашения о вызовах могут различаться (между x86 и x86_64); Параметры могут быть помещены в стек или помещены в регистр, и я не уверен, что вы точно знаете, где они будут.

Написание этого на ассемблере, если вы действительно не знаете, что делаете, может привести к неопределенному коду поведения.

1
По вопросам рекламы [email protected]