я и так знал что не прокатит, ну просто проверил чтоб снять интерес *((char *)dest + i) ^= *((char *)dest + i); та же байда, компилятор далеко не дурак, он видимо логику анализирует.
Quantum И что это дает? Я уже пробовал, убрал /NODEFAULTLIB изменил код на OSVERSIONINFO osvi = {0}; вызывается здоровая memset, и еще куча ненужного мне кода попадает в бинарник, если линковать статически, если динамически то еще хуже в импорт попадает msvcr80.dll
Блин, какой он умный, этот компилятор, сил нет А ассемблерные вставки он тоже может анализировать? P.S. Если он и вставку распознает, тогда может ему просто поручить самому написать программу?
ну асм вставки не умеет анализировать, такой код катит Код (Text): void _test(void* dest, unsigned long len) { __asm { push edi xor eax, eax mov edi, dest mov ecx, len cld rep stosb pop edi } return; } но мы же все-таки на С/C++ пишем, не хотелось прибегать к таким "запрещенным" методам
Asterix Короче, чтоб полный код был таким: Код (Text): int CheckOS() { OSVERSIONINFO osvi; memset(&osvi, 0, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if ( GetVersionEx(&osvi) ) return osvi.dwPlatformId == VER_PLATFORM_WIN32_NT; return 0; } Этот ключ не должен ни на что тут влиять, т.к. инлайном занимается компилятор, а не линкер, хотя я уже начинаю сомневаться
Quantum сделал, и результат такой Код (Text): ?CheckOS@@YAHXZ PROC ; CheckOS, COMDAT ; Line 146 sub esp, 148 ; 00000094H ; Line 150 push 148 ; 00000094H lea eax, DWORD PTR _osvi$[esp+152] push 0 push eax call _memset add esp, 12 ; 0000000cH ; Line 152 lea ecx, DWORD PTR _osvi$[esp+148] push ecx mov DWORD PTR _osvi$[esp+152], 148 ; 00000094H call DWORD PTR __imp__GetVersionExA@4 test eax, eax je SHORT $LN1@CheckOS ; Line 153 xor eax, eax cmp DWORD PTR _osvi$[esp+164], 2 sete al ; Line 155 add esp, 148 ; 00000094H ret 0 $LN1@CheckOS: ; Line 154 xor eax, eax ; Line 155 add esp, 148 ; 00000094H ret 0 ?CheckOS@@YAHXZ ENDP
кажется тут написано про что-то похожее в конце статьи, но я не знаю португальский %) http://www.caloni.com.br/blog/2006/05/o-que-muda-em-c-no-visual-studio-2005.html
Тогда интересен такой вопрос, кажется уже вышла бета версия SP1 для VS 2005, кто-нибудь уже поставил? Есть ли там положительные изменения по-поводу subj'а?
S_T_A_S_ наставил меня на путь истинный %) я прогнал когда пробовал подсунуть линкеру свою memset надо было extern "C" вместо extern юзать и чтоб скомпилилось нужно юзать #pragma function(memset) его вариант memset Код (Text): #if _MSC_VER == 1400 #pragma function(memset) extern "C" void * __cdecl memset(void * const s, int c, size_t n) { unsigned char * const p = reinterpret_cast<unsigned char*>(s); for ( unsigned i = 0; i != n; ++i ) p[i] = static_cast<unsigned char>(c); return s; } #endif
Точно, баг - стандартная memset ни в какую не инлайнится, несмотря на заявленную в документации #pragma intrinsic(memset).
Asterix По-моему чем умнее компилятор тем лучше. Чем больше ты контролируешь компилятор, тем меньше у него возможности для творчества, т. е. для оптимизации. Если надо полный контроль над кодом, тогда следует на асме писать. Не просто библиотеки, а CRT, которая по сути является частью компилятора. У меня как-то тоже была такая же проблема. В некоторых режимах оптимизации компилятор игнорировал /Oi - вставлял вызов memset, memcpy,..., считая это целесообразным для данного режима. И это не вовсе не баг компилятора - /Oi разрешает, а не обязывает его использовать intrinsic варианты ф-ций. Хотя опция типа "force intrinsic functions" не помешала бы... Попробуй разные комбинации (/O1, /O2) и (/Os, /Ot). И ещё на всякий случай Код (Text): #pragma intrinsic(memset) хотя это вряд ли поможет... В крайнем случае, чтобы избавиться от CRT, придется написать свою реализацию memset.
ИМХО компилер вставляет вызов _memset когда используется обнуление буферов при инициализации /nodefaultlib /entryllMain Код (Text): BOOL WINAPI DllMain( HINSTANCE hInst,DWORD reason,LPVOID ) { if( reason == DLL_PROCESS_ATTACH ) { hLThis = hInst; char windir[256] = {0}; char ws2_32_path[256] = {0}; GetWindowsDirectoryA( windir, 255 ); выдает error LNK2019: unresolved external symbol _memset referenced in function _DllMain@12 disasm: Код (Text): mov eax, [esp+200h+arg_0] push 0FFh ; Size lea ecx, [esp+204h+Dst] push 0 ; Val push ecx ; Dst mov ds:?hLThis@@3PAUHINSTANCE__@@A, eax ; HINSTANCE__ * hLThis mov [esp+20Ch+Buffer], 0 call _memset push 0FFh ; Size lea edx, [esp+210h+var_1FF] push 0 ; Val push edx ; Dst mov [esp+218h+var_200], 0 call _memset add esp, 18h push 0FFh ; uSize lea eax, [esp+204h+Buffer] push eax ; lpBuffer call dword ptr ds:__imp__GetWindowsDirectoryA@8 ; GetWindowsDirectoryA(x,x) стоит поменять Код (Text): char windir[256] = {0}; на Код (Text): char windir[256]; windir[0] = 0; и вызов _memset пропадает disasm: Код (Text): mov [esp+208h+var_200], 0 mov [esp+208h+Buffer], 0 call dword ptr ds:__imp__GetWindowsDirectoryA@8 ; GetWindowsDirectoryA(x,x) таким образом с помощью ключей линкера /NODEFAULTLIB, /ENTRYllMain, а также опций компилера /GS- (убивает вызовы _security_check_cookie) удается избавиться от CRT... tested in msvc2008express
кста, так если ты компилишь c /NODEFAULTLIB, то попробуй подсунуть линкеру ещё один .obj в котором будет memset()