Вопрос, собственно, следующий: имеется код в котором у инструкций используются вычисляемые выражения типа: mov byte ptr [ebp-((m0 -m1)-2)],(mm-m2) Ml.exe для выражений попадающих в диапазон 0-7Fh может сгенерить как «короткий» (imm8), так и «длинный» опкод. Так допустим, для вышеприведенного примера ((m0 -m1)-2)=33h, а (mm-m2)=45h т.е. в готовом виде эта строка выглядит как: ░.004010ED: C645CD45 mov b,[ebp][-33],045 а несколькими строчками ниже, она же выглядит по другому: ░.00401120: C685CDFFFFFF45 mov b,[ebp][-00000033],045 В результате ~20% различных инструкций (mov,sub/add,lea и пр.) где можно было бы обойтись байтом, используется dword. Хотя с точки зрения логики все правильно, только вот размер становится больше Можно, ли это как-нибудь это дело исправить?
BackDoor Покажы сорцы, что именно компилируется в длинную форму? > Например, Fasm по всегда генерирует минимальный по размеру опкод, если только ему явно не указать обратное. А masm IMHO довольно глючный =)
Как и полагается, забыл указать самое главное Под "выражениями" следует понимать разности офсетов, что встречается в кодах защит/вирей (у меня первый случай). Нормальный код, в силу некоторых обстоятельств, давать не буду Но для наглядности набил АБСОЛЮТНО ЛИШЕННЫЙ ЛОГИКИ код - так сказать краш-тест. Хотя я уже сомневаюсь, что "подобное" вообще какой-нибудь компилятор ужмет. Но если есть мысли напишите. Итак бред: ================= .code start: call DeltaInEBP lea edi,[ebp-(Delta-m2)] mov eax,[ebp-(Delta-m1)] mov eax,[ebp-(Delta-m2)] m1: add eax,1234567h mov edi,eax sub edx,(m2-m1) m2: mov esi,[ebp-(Delta-m1)] lea edi,[ebp-(Delta-m2)] xor esi,edi add ebx,(m5-m3) m3: mov eax,[ebp-(Delta-m1)] lea edi,[ebp-(Delta-m2)] m4: and esi,(m3-m2) mov esi,(m4-m2) m5: xor ebx,[ebp-(Delta-m3)] DeltaInEBP: call Delta Delta:: pop ebp ret end start ================= А это вот из ML-ного обджа ================= .text:00000000 public _start .text:00000000 _start proc near .text:00000000 E8 44 00 00 00 call sub_49 .text:00000005 8D 7D CD lea edi, [ebp-33h] .text:00000008 8B 45 C0 mov eax, [ebp-40h] .text:0000000B 8B 45 CD mov eax, [ebp-33h] .text:0000000E 05 67 45 23 01 add eax, 1234567h .text:00000013 8B F8 mov edi, eax .text:00000015 81 EA 0D 00 00 00 sub edx, 0Dh .text:0000001B 8B B5 C0 FF FF FF mov esi, [ebp-40h] .text:00000021 8D BD CD FF FF FF lea edi, [ebp-33h] .text:00000027 33 F7 xor esi, edi .text:00000029 81 C3 17 00 00 00 add ebx, 17h .text:0000002F 8B 85 C0 FF FF FF mov eax, [ebp-40h] .text:00000035 8D BD CD FF FF FF lea edi, [ebp-33h] .text:0000003B 81 E6 14 00 00 00 and esi, 14h .text:00000041 BE 20 00 00 00 mov esi, 20h ; ' ' .text:00000046 33 5D E1 xor ebx, [ebp-1Fh] .text:00000046 _start endp .text:00000049 sub_49 proc near ; CODE XREF: _startp .text:00000049 E8 00 00 00 00 call $+5 .text:0000004E 5D pop ebp .text:0000004F C3 retn .text:0000004F sub_49 endp =================
Код (Text): sub edx,(3-1) mov esi,[ebp-(40-10)] lea edi,[ebp-(25555-25500)] sub edx, 0Dh У меня перекомпилял MASM в 83EA02 sub edx,002 ;"☻" 8B75E2 mov esi,[ebp][-1E] 8D7DC9 lea edi,[ebp][-37] 83EA0D sub edx,00D ;"♪" А вот Код (Text): sub edx, 0222Dh ; Константа больше 255 :) Получил 81EA2D220000 sub edx,00000222D
IMHO проблема связана с тем, что на MASM лежит печать Баала и он не многопроходный. Поскольку метки ракиданы посреди команд, размер опкодов которых может быть разным, MASM просто тупо выбирает "стандартный" FASM рулит! Код (Text): 0.<Module>/$ E8 2F000000 call 0.00401034 00401005 |. 8D7D DF lea edi, [ebp-21] 00401008 |. 8B45 D5 mov eax, [ebp-2B] 0040100B |. 8B45 DF mov eax, [ebp-21] 0040100E |. 05 67452301 add eax, 1234567 00401013 |. 89C7 mov edi, eax 00401015 |. 83EA 0A sub edx, 0A 00401018 |. 8B75 D5 mov esi, [ebp-2B] 0040101B |. 8D7D DF lea edi, [ebp-21] 0040101E |. 31FE xor esi, edi 00401020 |. 83C3 0E add ebx, 0E 00401023 |. 8B45 D5 mov eax, [ebp-2B] 00401026 |. 8D7D DF lea edi, [ebp-21] 00401029 |. 83E6 0B and esi, 0B 0040102C |. BE 11000000 mov esi, 11 00401031 |. 335D EA xor ebx, [ebp-16] 00401034 |$ E8 00000000 call 0.00401039 00401039 |$ 5D pop ebp 0040103A \. C3 retn SteelRat Ты компилируешь команды по отдельности - это не то. BackDoor > Кстати, fasm может делаеть не только coff obj, но и сразу бинарку - бери и вставляй куда хошь. можно даже заксорить куски кода на сразу этапе компиляции.
Мда, действительно ФАСМ рулит. А какая последняя версия Ml.exe? Я пробовал 6.14.8444 и 7.10.3077, но результат одинаковый: ml идет "своим" путем...
В новом ML тоже самое, похоже тут особенность (или баг) проявляется тогда, когда будущий опкод находится между меток операнда, так получается коротким Код (Text): m1: m2: mov esi,[ebp-(m2-m1)] lea edi,[ebp-(Delta-m3)] m3: Delta: Или так ещё, эти закодируются длинными, но если убрать call Delta, то lea получится коротким Код (Text): m1: m2: mov esi,[ebp-(Delta-m1)] lea edi,[ebp-(Delta-m2)] call Delta Delta: маразм короче
Это не совсем маразм. МАСМ - классический 2х проходной ассемблер: на первом проходе он составляет таблицу меток, т.е. определяет m1 и m2 - но он в этот момент не знает, сколько байт будет опкод lea edi,[ebp-(Delta-m2)] ! Поэтому выбирает 4х байтный операнд. Потом он просто ассемблирует [-(Delta-m2)] в dword. А fasm при этом определяет, что возможно закодировать команду более компактно, переопределяет метки и делает ещё один проход и т.д.
Хотя тасм и устарел, но скомилил все короткими опкодами Использовал: tasm32.exe /m /ml /z example.asm Так что Ml.exe проигрывает 2:0