Хрестоматийный пример зачем нужно знать формат. Закодируй вручную при этом в sib в index поставь 100 а в scale 00 (это будет означать отсутвие индекса), edi (111)поставь в base и всё. Тогда ebp не понадобится при той же длине инструкции. Например MOV EAX,[EBP+EDI+400000] это в Hex 8B 84 3D 00 00 40 00 8B - это инструкция с указанием размера 84 3D - это modrm и sib 3D - sib раскладывается как 00 111 101 00 - маштабирование 111 - код индекса (edi) 101 - код базы (ebp) чтобы индекс вообще не использовать можно сделать так 00 100 111 00 100 - указывает что индекса нет 111 - базовый edi. в HEX будет 27 т.е. весь опкод должен быть 8B 84 27 00 00 40 00 Это будет не что иное как MOV EAX,[EDI+400000] но в альтернативной кодировке Оптимальная кодировка будет 8B 87 00 00 40 00 это тоже MOV EAX,[EDI+400000] здесь edi кодируется в modrm (как обычно ассемблер и делает) а выше приведена альтернативная кодировка на байт длинее с использованием sib. можно и по другому - сделать индекс без базы. Я как то статью пытался написать про как раз использование альтернативного кодирования именно в целях выравнивания (что на данный момент не делает ни один ассемблер) но мне показалось логичным приложить тогда уж тулзу для этого, а тулза получалась вроде как целым ассемблером со втроенной фичей, и что-то я остановился в раздумье начинать ли )
Забыл написать без базы: 8B 04 3D 00 00 40 00 84 меняешь на 04 (снимаешь 10 в mod - в сочитании mod=00 base = 101 означает - нет базы один displacement)
TheSvin Кодирование "вручную" это конечно супер. Изредка балуюсь этим делом, но поскольку на память ничего не помню, приходится лазить за подзказками к интеловскому мануалу - получается не быстро. А вообще-то я эти проверки с выравниванием затеял только ради интереса. После "тыканья в потемках" и твоей дельной критики пришлось взяться за ликбез. Теперь хоть какое-то разумное представление складывается и ес-но по ходу возникакают кой-какие мыслишки и желание их проверить.
The Svin > А были ли мысли относительно синтаксиса? Я имею ввиду, как сказать транстлятору, что данную команду нужно кодировать минимальным по размеру опкодом, а другую - user defined ? С ходу приходит на ум вариант с различным положением скобочек: [base+scale*index+displasement] - оптимизируется по размеру [base][scale*index][displasement] - не оптимизируется по размеру Приминительно к рассмотренному примеру это могло бы выглядеть так: Код (Text): MOV EAX,[EDI+400000] ; 8B 87 00 00 40 00 MOV EAX,[EDI][][400000] ; 8B 84 27 00 00 40 00 Хотя все возможные проблемы это не решает, например, нужно учесть варианты использования disp32, вместо disp8, или случаи когда disp нужно закодировать, но в оптимальном случае он не нужен.. можно добавить (при необходимости) оператор размерности: Код (Text): MOV EAX,[EDI] ; 8B 07 MOV EAX,[EDI][][byte 0] ; 8B 44 27 00 MOV EAX,[EDI][][dword 0] ; 8B 84 27 00 00 00 00 Конечно рассмотреный вариант можно без кодирования вручную так записать: MOV EAX,[ES:EDI+400000] ; 26 8B 87 00 00 40 00 Но речь не об этом, сама идея использовать в ассемблере возможность кодирования различных форматов очень интересная, вот только через DB это как-то не очень красиво делать
Чтобы программно реализованное это могло быть эффективным, это несомненно должно быть частью ассемблера. Однако, это должно применяться не к отдельным инструкциям. С помощью различных методов кодирования адресации длина не может быть настроена с точностью до байта... Лучше если будет возможность указывать блок кода, который нужно выровнять. А ассемблер будет пытаться добиться желаемого (например, сделать размер кода блока в байтах кратным 16) варьируя метод кодирования адресации всех инструкций блока...
Во-первых, все слова, у которых первая буква '#' выглядят подозрительно. Во-вторых, данная возможность обычно будет применятся для выравнивания где важна только кратность, а не фактический размер. Поэтому средство должно позволять указывать не точный размер блока в байтах, а число (степень двойки), которому размер должен быть кратен. Каков именно будет этот кратный размер - программисту знать не обязательно, это будет проблема транслятора.
Основная идея в том, что выравнивание которое и сейчас уже существует (например ALIGN) и выполняется вставкой пустых инструкций (не обязательно NOP но по логике тот же NOP, например каким-нить Lea eax,[eax][0000000] и т.п) выполнялось не вставкой а удлинением инструкции это дополнительное удлинение и заменит все NOPы но при этом не увеличит количество инструкций. На самом деле я вроде видел эту же идею воплощённую в результате работы каког-то компилятора, но там было сделано наихудшим и очень ограниченным по возможностям способом - добавлением префиксов переопределения сегмента которые указаывали на тот же дефолтный сегмент, но указывали явно. Наиболее интересные, эффективные и гибкие возможности даёт альтернативное кодирование modrm, это авторов компиляторов видимо ломает писать (если вообще они понимают что-то в этом) гораздо проще в логике компилятора им впендюрить nop'ов нужной длины или насобачить префиксов. Наиболее эффективно IMHO будет альтернативное кодирование когда на узком участке нужно выравнять несколько меток, так бывает со вложенными циклами в купе с необходимостью выравнивать сам вход в короткую и часто вызываемую процедуры где к тому же возможно есть сложное ветвление в блоках управления и вход в какие-то ветки тоже хорошо бы выравнять. Т.е. в кратце то о чём мы говорили здесь - как сделать выравнивание без нопоподобных вставок, обойдясь альтернативным кодированием.
Ага, речь идёт об "интеллектуальном" операторе align. Который будет подбирает для предшествующих команд опкоды определённых размеров. С другой стороны, случаи, когда необходимо точно знать размер опкодов так же существуют - например констукции типа switch (jmp eax). Таким образом, IHMO необходимо две фичи. > гораздо проще в логике компилятора им впендюрить nop'ов нужной длины или насобачить префиксов. Да, это конечно проще, встретили align, кол-во нопов подсчитать не проблема. Если мы говорим компилятору, что некий кусок должен быть NN байт, до того как он его будет компилировать, то тут ему проще соображать будет.. Но если говорить о варианте с "удлиннением" предыдущих опкодов, то логика компилятора будет несколько сложнее. "Возвращаться назад" нужно будет или компилировать за кучу проходов.. К чему я это - то, как это будет записано в исходнике, влияет на сложность реальзации. очевидно, что традиционная директива ALIGN не будет наилучшим решением :-( ЗЫ А почему '#' выглядит подозрительно ? : ) ЗЫЫ Гы, что-то я тут оффтоп развёл =)