Здравствуйте, Patalog, Вы писали:
N>>Хранение в процессе использования внутри функции разных параметров, например, рядом в AL и AH — тоже нет, компиляторы такое не делают — им это ломает логику распределения регистров.
P>Тут не буду спорить, но когда я последний раз глядел в эту сторону (году этак в 12-13м) — вполне себе видел код со всеми этими прелестями EAXов уж точно,
Именно для x86 тут есть принципиальная разница:
1. Большинство команд в 32-битном варианте короче (нет REX префикса).
2. Исполнение команды над 32-битными версиями регистров чистит старшие 32 бита регистра, поэтому зависимости от предыдущего значения архитектурного регистра не создаётся. А вот для операций с xL, xH, xX (x=A,B,C,D), SIL, DIL... чистки верхней части не происходит, это специфическое наследие x86 из 1980-х, когда они об этом не думали. (Почему не думали — не знаю, OoO с переименованием регистров растёт минимум из 1969, но у Intel собственная гордость.)
Поэтому оптимизация с работой с EAX вместо RAX и т.п. — полезна, а с AX, AL, AH — уже (почти всегда) нет.
Работу с AH можно найти или в ручном ассемблерном коде, или в результате peephole-оптимизаций, где, например, b = a>>8; заменяется на извлечение AH (и то, только в случае если значение уже сидит в регистре, а писать в память).
Типовые более современные RISC-архитектуры (ARM, RISC-V) не имеют подобной специфики потому, что у них вообще нет неполной загрузки в регистр, любое загруженное значение расширяется до полной ширины. В ARM, если таковая нужна, надо сначала загрузить во временный регистр, а потом доработать командой группы BFM. Аналогичное есть, например, в SystemZ (IC, RISBG и тому подобные команды).
P> насчет AH/AL в свеже сгенеренном коде врать не буду, не помню, а вот в каких-то из системных библиотек 7-ки, в котором приходилось ковырятся отладчиком (была тема самопального PE загрузчика) — точно были.