ntldr вы просто спорите о разных вещах. Если я правильно догадался, тебе загрузчик этот нужен для твоего проекта по шифрованию разделов. И в нём тебе надо реализовывать криптоалгоритмы, так? Тогда действительно твой подход с переходом в PM и использованием 32-битного кода лучше. Но для простого MBR задача супер максимум это показать меню чтобы пользователь выбрал с какого раздела грузиться, загрузить с него BootSector и передать ему управление. В этом случае 16-битный код будет оптимальнее, и спокойно влезет в 512 байт. Кстати Watcom C очень неплохо оптимизирует и его линкер умеет собирать чистые бинарники. (www.openwatcom.org)
Вы прикалываетесь? Пробовал я этот Watcom C, ничего хуже я никогда раньше не видел. Он выдает не просто плохой, а ОЧЕНЬ плохой код в котором оптимизацией даже и не пахнет. Borland c 3.1 по сравнению с ним просто шедевр оптимизации
Нет, не прикалываюсь. Я начал пользоваться с версии по-моему 1.5 - вроди нормальный код генерирует... А на какой например сишный код бинарник не оптимальный генерируется? И всё равно во многих аспектах у него вообще нет конкурентов. Я например не знаю больше ни одного компилятора способного компилировать 32-битный код для х86 с сегментированной моделью памяти. Всё вышенаписанное относится к Open Watcom C++ 32-bit Optimizing Compiler, 16-битным я особо не пользовался.
Вот например: Код (Text): int mul20(int x) { return x*20; } int main(void) { int x=3; return mul20(x); } WC++ 1.6 wcc386 -6r -fp6 -fpi87 -otrnl+ -s test.c Код (Text): _TEXT SEGMENT PARA PUBLIC USE32 'CODE' ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP mul20_: push edx mov edx,eax shl eax,2 add eax,edx shl eax,2 pop edx ret lea eax,[eax] main_: mov eax,3 jmp mul20_ _TEXT ENDS VC++ 6.0 SP6 cl /G6 /Ot /Oy /Gs /Gr /c test.c Код (Text): @mul20@4: push ebp mov ebp,esp push ecx mov dword ptr [ebp-0x4],ecx mov eax,dword ptr [ebp-0x4] imul eax,0x00000014 mov esp,ebp pop ebp ret _main: push ebp mov ebp,esp push ecx mov dword ptr [ebp-0x4],0x00000003 mov ecx,dword ptr [ebp-0x4] call near ptr @mul20@4 mov esp,ebp pop ebp ret Жаль нету под рукой VS2005 чтоб попробовать. Но если сравнивать VC++6 и Watcom, то Watcom меня гораздо больше радует.
Поправка, на работе оказался VC++ 6.0 SP6 Sandart - потому такая оптимизация фиговая. Вот код сгенерированный Professional версией: VC++ 6.0 SP6 Pro cl /Ox /G6 /Gr /Gs /c test.c Код (Text): @mul20@4: lea eax,[ecx+ecx*4] shl eax,0x02 ret nop nop nop nop nop nop nop nop nop _main: mov ecx,0x00000003 jmp near ptr @mul20@4 nop nop nop nop nop nop VS 2005 Professional cl /Ox /O2 /Ot /Gr /c test.c Код (Text): @mul20@4: lea eax,[ecx+ecx*4] add eax,eax add eax,eax ret _main: mov eax,0x0000003c ret Везде использовал fastcall чтобы было по честному, Watcom по умолчанию параметры в регистрах передаёт. Ну и по коду - в плане быстродействия особой разницы нет. По крайней мере не на столько чтобы говорить что код ОЧЕНЬ плохой. Хотя если честно то мне больше всего нравится код сгенерированный VC++ 6.0 Pro, т.е. на ASM я бы написал lea eax,[eax*4+eax]/shl eax,2 Вот почему VS2005 вместо shl eax,2 предпочла add eax,eax/add eax,eax - мне не очень понятно... А вот к примеру умножение на 21: Watcom: Код (Text): push edx mov edx,eax shl eax,2 add eax,edx shl eax,2 add eax,edx pop edx ret VS2005 Код (Text): mov eax,ecx imul eax,0x00000015 ret Тут по-моему всё-таки быстрее будет работать вариант с разложением, чем умножение через imul. В общем не всё так однозначно...
icc 10 Код (Text): int __fastcall mul20(int x) { return x * 20; } Код (Text): lea eax, DWORD PTR [ecx+ecx*4] ;6.14 shl eax, 2 ;6.14 ret ;6.14 Код (Text): int __fastcall mul20(int x) { return x * 21; } Код (Text): imul eax, ecx, 21 ;6.14 ret ;6.14 ага? надо vtune поставить и посмотреть.
Delphi 7: Код (Text): Result:=x*20; shl EAX, 2 lea EAX, [EAX + EAX * 4] Код (Text): Result:=x*21 imul EAX, EAX, 0x15
VC 2008 (/O2): Код (Text): _mul20 PROC mov eax, DWORD PTR _x$[esp-4] lea eax, DWORD PTR [eax+eax*4] add eax, eax add eax, eax ret 0 _mul20 ENDP _main2 PROC mov eax, 60 ; 0000003cH ret 0 _main2 ENDP Насчёт загрузчика на С - можно линковать без релоков (/fixed), указав базовый адрес (/base) равным загрузочному минус 4К. Потом у полученного ехе отрезать заголовок. Можно также объединить секции.
green как и у VS2005 - только у тебя не fastcall функция. Да в этом смысла нет - всё равно код будет 32-битный, а CPU после загрузки в 16-битном RM. Т.е. нужен как минимум 16-битный загрузчик который загрузит наш PE и перейдёт в 32bit PM. Ну а он уже может и заголовок проанализировать, особенно если в PE нет релоков и он собран по нужному базовому адресу
Кстаи если у кого vtune стоит - можете сравнить? Код (Text): push edx mov edx,eax shl eax,2 add eax,edx shl eax,2 add eax,edx pop edx ret Код (Text): mov eax,ecx imul eax,0x00000015 ret Код (Text): imul eax, ecx, 21 ;6.14 ret А то у меня VTune не установлен, да и процессор AMD, так что VTune не поможет. Может тему отдельную создать по сравнению компиляторов - а то жестокий оффтопик :/ Модераторы - если есть возможность и не лень - отрежте кусок темы с конца наверное где-то с 26 поста в отдельную тему.
Кстати вот ещё вариант Код (Text): LEA EAX,DWORD PTR DS:[ECX*8] SUB EAX,ECX LEA EAX,DWORD PTR DS:[EAX+EAX*2] RETN
Да, давайте тему про компиляторы. У кого-нить есть жесткие тесты для компилятора? надо проверить. Я уверен Делфи рулит.
Не смеши. Честно говоря мне смешны ваши примеры на которых вы сравниваете оптимизацию. Оптимизация это не только умение умножать x * 20. Поэтому для тестов нужно брать достаточно большой и сложный алгоритм из тех что применяются в реальных задачах.
И все эти алгоритмы так или иначе базируются на тех же арифметических операциях, в том числе умножении. Я не говорю что умножение на 21 является показательным и полным примером для оценки оптимизатора. Но кое-какие выводы сделать всё-таки можно.
Тема не та, что бы в ней перформанс компиляторов тестить. Но все же.. http://www.gamedev.ru/flame/forum/?id=12025&page=4 55 пост.