Можно ли в C написать DlgProc чтоб код был с одним ret(максимум двумя)..

Тема в разделе "WASM.WIN32", создана пользователем Asterix, 1 окт 2004.

  1. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Можно ли в C написать DlgProc чтоб код был с одним ret(максимум двумя),

    а то компилятор понапихал мне эпилог+ret заместо каждого return TRUE

    или break или может какие ключи при компиляции заюзать, это же безобразие

    какое-то.
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Asterix

    Покажи свой код, оповести о компиляторе, и об используемых ключах.
     
  3. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Я себе на днях поставил MS Visual C++ Toolkit , хочу посмотреть , что этот Си из себя представляет . Потом прочитал на uinc статью об уменьшении размера , получилось 1 Кб , нагуглил какой-то "naked" , чтоб прологи убрать , вроде получилось , теперь думаю как поубирать int3 (зачем-то понапихал компилер , выравнивает что-ли) и ещё можно ли сделать без заглушек , сразу call dword [ExitProcess] .



    Компилю такой строкой "d:\c++\bin\cl /I d:\c++\include /Od test.c /link /SUBSYSTEM:WINDOWS /NOLOGO /RELEASE /LIBPATH:d:\c++\lib" , вот код :
    Код (Text):
    1. //=====================================================
    2. #pragma comment(linker,"/MERGE:.rdata=.text")
    3. #pragma comment(linker,"/ALIGN:512 /SECTION:.text,EWRX")
    4. #pragma comment(linker,"/ENTRY:start")
    5. //=====================================================
    6. #pragma comment(lib,"kernel32.lib")
    7. //=====================================================
    8. void  __stdcall ExitProcess(unsigned long);
    9. //=====================================================
    10. __declspec     (naked) start ()
    11. {
    12.         ExitProcess(0);
    13. }
    14. //=====================================================
    з.ы. а си дворды не понимает ? Надо обязательно писать "typedef unsigned long dword;" ?
     
  4. n0p

    n0p 10010000b

    Публикаций:
    0
    Регистрация:
    7 май 2003
    Сообщения:
    256
    Адрес:
    Новосиbeerск
    Понимает, только если в верхнем регистре: не dword, а DWORD. Кстати, это и будет typedef unsigned long DWORD :)



    А насчет обрезания: я вот про naked не уловил сути. У меня все и без этого нормально работало.
    Код (Text):
    1. #include <windows.h>
    2. void EntryPoint()
    3. {
    4.   MessageBox(0,"zzz","dbg",MB_OK);
    5.   ExitProcess(0);
    6. }


    Только настройки компилера и линкера не могу показать - они в VS2k3 через гуй делаются и все скрытно. Хотя, говорят, где-то есть и нормальный способ настраивания.. :)
     
  5. Fallout

    Fallout New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2004
    Сообщения:
    94
    Адрес:
    Russia
    __declspec (naked) start ()

    {

    ExitProcess(0);

    }



    а ты ret поставь в конце и int 3 не будет +) это же голая функция... тут всё надо самому делать +)



    __declspec (naked) start ()

    {

    ExitProcess(0);

    __asm{

    ret

    }

    }
     
  6. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    bogrus

    теперь думаю как поубирать int3

    Imho не надо. Однако если хочешь, то используй ключ /Os favor code space.



    + можно прагмить ключ /SUBSYSTEM



    n0p

    Только настройки компилера и линкера не могу показать

    Новая студия не умеет делать makefile или его аналог?



    Fallout

    а ты ret поставь в конце и int 3

    Заблуждаешься. Попробуй добавить еще подпрограмм. Между ними появятся CCh и не по одной. Это выравнивание и страховка от несанкционированного выполнения.
     
  7. Fallout

    Fallout New Member

    Публикаций:
    0
    Регистрация:
    25 апр 2004
    Сообщения:
    94
    Адрес:
    Russia
    Мде +)... спасибо
     
  8. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    q_q

    > Покажи свой код, оповести о компиляторе, и об используемых ключах.



    компилятор из MS VC++ 6.0

    ключи CL=%CL% /nologo /GF /W4 /DNDEBUG /Ox /c
    Код (Text):
    1. #include <windows.h>
    2. #pragma comment(lib, "user32.lib")
    3. #pragma comment(linker, "/opt:nowin98")
    4. #include "resource.h"
    5.  
    6.  
    7. BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    8.  {
    9.    switch(msg)
    10.      {
    11.         case WM_INITDIALOG:
    12.               SendDlgItemMessage(hwnd, IDC_EDIT_1, EM_SETLIMITTEXT, 8, 0);
    13.               return TRUE;
    14.  
    15.         case WM_CLOSE:
    16.               EndDialog(hwnd, 0);
    17.               return TRUE;
    18.  
    19.         case WM_COMMAND:
    20.            switch(LOWORD(wParam))
    21.              {
    22.                 case IDC_BUTTON_1:
    23.                       return TRUE;
    24.  
    25.                 case IDC_BUTTON_2:
    26.                       MessageBox(hwnd, TEXT("text"), TEXT("About"), MB_OK);
    27.                       return TRUE;
    28.  
    29.                 case IDC_BUTTON_3:
    30.                       SendMessage(hwnd, WM_CLOSE, 0, 0);
    31.                       return TRUE;
    32.              }
    33.      }
    34.     return FALSE;
    35.  }
    36.  
    37. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
    38.  {
    39.    return DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG_1), 0, DlgProc);
    40.  }
     
  9. _Juicy

    _Juicy Active Member

    Публикаций:
    0
    Регистрация:
    12 авг 2003
    Сообщения:
    1.159
    Адрес:
    SPb
    /Os рулит в данном случае
     
  10. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Asterix

    компилятор понапихал мне эпилог+ret

    Т.к. используется /Ox, то работу по оптимизации ты возлагаешь на компилятор, программа же изобилует return'ам, а не break'ами. Т.к. /Ox == /Ogityb1 + /Gs, а /Ot - оптимизация по скорости, то компилятор прав, ибо с точки зрения скорости, лучше ret, чем jmp + ret.
     
  11. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    q_q

    > Т.к. используется /Ox



    А что нужно использовать, /O1 ??

    Рекомендации ??



    > программа же изобилует return'ам



    Тоже самое будет если return'ы заменить на break'и..
     
  12. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Asterix

    Тоже самое будет если return'ы заменить на break'и..

    А /Ox убрал?



    Рекомендации

    Например, если убрать /Ox, то такой код обойдется без лишних ret'ов
    Код (Text):
    1. BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    2. {
    3.   BOOL r = TRUE;
    4.  
    5.   switch(msg)
    6.   {
    7.   case WM_INITDIALOG:
    8.     SendDlgItemMessage(hwnd, IDC_EDIT_1, EM_SETLIMITTEXT, 8, 0);
    9.     break;
    10.   case WM_CLOSE:
    11.     EndDialog(hwnd, 0);
    12.     break;
    13.   case WM_COMMAND:
    14.     switch(LOWORD(wParam))
    15.     {
    16.     case IDC_BUTTON_1:
    17.       break;
    18.     case IDC_BUTTON_2:
    19.       MessageBox(hwnd, TEXT("text"), TEXT("About"), MB_OK);
    20.       break;
    21.     case IDC_BUTTON_3:
    22.       SendMessage(hwnd, WM_CLOSE, 0, 0);
    23.       break;
    24.     }
    25.   default:
    26.     r = FALSE;
    27.   }
    28.   return r;
    29. }
    :) если написать так, то можно оставить /Ox
    Код (Text):
    1. BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    2. {
    3.   BOOL r = TRUE;
    4.  
    5.   switch(msg)
    6.   {
    7.   case WM_INITDIALOG:
    8.     SendDlgItemMessage(hwnd, IDC_EDIT_1, EM_SETLIMITTEXT, 8, 0);
    9.     goto l1;
    10.   case WM_CLOSE:
    11.     EndDialog(hwnd, 0);
    12.     goto l1;
    13.   case WM_COMMAND:
    14.     switch(LOWORD(wParam))
    15.     {
    16.     case IDC_BUTTON_1:
    17.       goto l1;
    18.     case IDC_BUTTON_2:
    19.       MessageBox(hwnd, TEXT("text"), TEXT("About"), MB_OK);
    20.       goto l1;
    21.     case IDC_BUTTON_3:
    22.       SendMessage(hwnd, WM_CLOSE, 0, 0);
    23.       goto l1;
    24.     }
    25.   }
    26.   r = FALSE;
    27. l1:
    28.   return r;
    29. }
    Итого: если пишешь на Си, то прекращай думать по ассемблерщик, доверяй компилятору.



    bogrus

    сразу call dword [ExitProcess]

    Ты стал "заложником" своего подхода (пытаешься обойтись без psdk), попробуй так
    Код (Text):
    1.  
    2. #include <windows.h>
    3. #pragma comment(linker,"/MERGE:.rdata=.text")
    4. #pragma comment(linker,"/ALIGN:512 /SECTION:.text,EWRX")
    5. #pragma comment(linker,"/ENTRY:start")
    6. #pragma comment(linker,"/SUBSYSTEM:WINDOWS")
    7. #pragma comment(lib,"kernel32.lib")
    8. __declspec(naked) start ()
    9. {
    10.   ExitProcess(0);
    11. }
    в результате см снимок из Olly



    [​IMG] _1617374789__olly.gif
     
  13. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    q_q

    Ладно, с этим разобрались, хотя я не согласен с присваиванием переменной значения TRUE в начале, код получается некрасивый, я бы сделал по другому :derisive:



    Как мне вот здесь избавится от ret после ExitProcess(0)

    догадываюсь что нужны какие-то трюки с __declspec
    Код (Text):
    1. void start(void)
    2. {
    3.    hInstance = GetModuleHandle(NULL);
    4.    DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG_1), 0, (DLGPROC) DlgProc, 0);
    5.    ExitProcess(0);
    6. }
     
  14. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Asterix

    я не согласен с присваиванием переменной значения TRUE в начале

    Зря. Инициализировать переменные - хорошая практика.



    Как мне вот здесь избавится от ret

    bogrus уже показал __declspec(naked).
     
  15. n0p

    n0p 10010000b

    Публикаций:
    0
    Регистрация:
    7 май 2003
    Сообщения:
    256
    Адрес:
    Новосиbeerск
    q_q



    Не знаю. Самостоятельно она его не делает, но может где-то глубоко в настройках и есть подобная фича.
     
  16. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    q_q




    Действительно , так гораздо лучше :)

    Просто windows.h и др. не идут с MS Visual C++ Toolkit 2003 , но благо нашёл на винте соседа заархивированный \DevStudio\VC98 .
     
  17. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    bogrus

    > Просто windows.h и др. не идут с MS Visual C++ Toolkit 2003



    они идут с psdk, размер которого в минимальном варианте ~40Mb :derisive:
     
  18. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    q_q

    > bogrus уже показал __declspec(naked)



    Что-то я не понял как мне применить в моём случае, компилятор почему-то ругается.
    Код (Text):
    1. mini.cpp(22) : error C2561: 'start' : function must return a value
    2.         mini.cpp(16) : see declaration of 'start'
     
  19. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Asterix

    Показывай весь код.
     
  20. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    q_q

    Вот:
    Код (Text):
    1.  
    2. #include <windows.h>
    3. #include "resource.h"
    4.  
    5.  
    6. #pragma comment(linker, "/ENTRY:start")
    7. #pragma comment(linker, "/opt:nowin98")
    8. #pragma comment(lib, "kernel32.lib")
    9. #pragma comment(lib, "user32.lib")
    10.  
    11.  
    12. BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    13. HINSTANCE     hInstance;
    14.  
    15.  
    16. // void start(void)
    17. __declspec(naked) start ()
    18. {
    19.    hInstance = GetModuleHandle(NULL);
    20.    DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG_1), 0, (DLGPROC) DlgProc, 0);
    21.    ExitProcess(0);
    22. }
    23.  
    24.  
    25. BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    26. {
    27.   BOOL r = TRUE;
    28.  
    29.   switch(msg)
    30.   {
    31.    case WM_INITDIALOG:
    32.       SendMessage(hwnd, WM_SETICON, ICON_BIG,
    33.                  (LPARAM) LoadIcon(hInstance, MAKEINTRESOURCE(MAINICON)));
    34.       SendMessage(hwnd, WM_SETICON, ICON_SMALL,
    35.                  (LPARAM) LoadImage(hInstance, MAKEINTRESOURCE(MAINICON), IMAGE_ICON, 16, 16, 0));
    36.       break;
    37.    case WM_CLOSE:
    38.       EndDialog(hwnd, 0);
    39.       break;
    40.    case WM_COMMAND:
    41.      switch(LOWORD(wParam))
    42.      {
    43.       case IDB_PLAY:
    44.          break;
    45.       case IDB_STOP:
    46.          break;
    47.       case IDB_EXIT:
    48.          SendMessage(hwnd, WM_CLOSE, 0, 0);
    49.          break;
    50.       default:
    51.        r = FALSE;
    52.      }
    53.   }
    54.   return r;
    55. }