Да, сделайте это, если ваш код будет работать быстрее и/или в целом станет меньше.
Одним из преимуществ ручного написания на ассемблере является возможность использовать пользовательские функции соглашений о вызовах, даже если они не являются частными вспомогательными функциями или макросами. Это включает в себя возможность «возвращать» несколько значений в разных регистрах и в основном делать все, что вы хотите.
Как и в случае любого пользовательского соглашения о вызовах, все, что вам нужно сделать, это задокументировать его с комментариями. Вот пример того, как можно написать такие комментарии, с конкретным и заведомо нестандартным набором вещей.
# inputs: foo in EAX (zero-extended into RAX), bar in EDI
# pre-requisites: DF=0
# clobbers: RCX, RDX, AL (but not the rest of EAX)
# returns: AL = something, ZF = something else
my_func:
...
setc al
...
something that sets ZF
ret
Если вы готовы пожертвовать эффективностью ради стиля или удобочитаемости, вам, вероятно, не стоит писать на ассемблере в первую очередь в 2018 году, когда компиляторы в большинстве случаев способны генерировать хороший ассемблер, и вам редко нужно писать собственный загрузочный код. сектор или что-то еще. (т. е. производительность является основным вариантом использования, оставленным для написанного от руки ассемблера, и это уместно только в том случае, если вы делаете все возможное для производительности.)
Да, написанный от руки ассемблер может превратиться в нечитаемый/неподдающийся сопровождению беспорядок, но если все сделано аккуратно, когда он имеет разумное семантическое значение, эта оптимизация не сделает ваш код беспорядочным.
Для этого даже есть прецедент: системные вызовы x86-64 OS X использовать CF в качестве статуса ошибки/отсутствия ошибки, отдельно от возвращаемого значения rax
. В отличие от Linux, где ошибки обозначаются возвращаемыми значениями RAX от -4095 до -1, хотя в остальном они используют одно и то же соглашение x86-64 System V ABI/вызовов.
Некоторые системные вызовы DOS int 0x21
и функции PC BIOS int 0x10
имеют аналогичную систему возврата флагов. Он позволяет вызывающей стороне переходить при ошибке, поэтому экономит размер кода (тест или cmp) и позволяет избежать необходимости внутриполосной сигнализации об ошибках.
22.01.2018
_Bool
выполнялся путем установки флага. Использование регистра для возврата_Bool
кажется мне пустой тратой времени. 27.05.2019add
илиsub
для очистки фрейма стека, но они могут LEA. Или отложите фактическую операцию установки флага до момента возврата после запуска деструкторов. Но самая большая проблема: какой флаг вы бы выбрали? CF — очевидный выбор (потому что для его использования есть специальные инструкции, напримерadc
/sbb
), и некоторые специальные инструкции задают его (bt
/bts
и т. д.,rdrand
). Но если ваш_Bool
поступает из ZF из такой инструкции, какbsr
илиbsr
, или сравнения==
, или сравнения SF + OF со знаком, вы, вероятно. нужен сете/ле + смп. 27.05.2019