Интересно сможет ли кто нибудь уменьшить размер данной программы настолько насколько это возможно??? У меня она весит 4096 байт. Эй, гуру ассемблера, проявите себя, помогите пытливому человеку... О проге: прога-генератор серийника для WinZip 9.0......но пока без процедуры генерации.....))) сначала была написана на чистом API в Дельфи....но 18 Кб мне показалось много....решил на ассемблере (MASM32). Начало впечатляет 4 Кб.....но можно ли еще меньше?)))) Code (Text): .386P ; сплошная модель памяти .MODEL FLAT, stdcall ;==================================================== ;константы ;==================================================== WM_SETFONT equ 30h BN_CLICKED equ 0 WM_COMMAND equ 111h DEFAULT_CHARSET equ 1 OUT_DEFAULT_PRECIS equ 0 CLIP_DEFAULT_PRECIS equ 0 DEFAULT_QUALITY equ 0 DEFAULT_PITCH equ 0 WM_SETFOCUS equ 7h WS_OVERLAPPED equ 0h ; сообщение приходит при закрытии окна WM_DESTROY equ 2 ; сообщение приходит при создании окна WM_CREATE equ 1 WM_KEYDOWN equ 100h SM_CXSCREEN equ 0 SM_CYSCREEN equ 1 ; сообщение, позволяющее послать элементу строку WM_SETTEXT equ 0Ch ; сообщение, позволяющее получить строку WM_GETTEXT equ 0Dh ; свойства окна CS_VREDRAW equ 1h CS_HREDRAW equ 2h CS_GLOBALCLASS equ 4000h WS_TABSTOP equ 10000h WS_SYSMENU equ 50000h WS_OVERLAPPEDWINDOW equ 000CF0000H CS_PARENTDC equ 80h style equ CS_PARENTDC BS_DEFPUSHBUTTON equ 1h WS_VISIBLE equ 10000000h WS_CHILD equ 40000000h WS_BORDER equ 800000h ES_AUTOHSCROLL equ 80h WS_EX_CLIENTEDGE equ 00000200h BS_TEXT equ 0 WINDOWSTYLE equ WS_OVERLAPPEDWINDOW STYLBTN equ WS_CHILD+BS_TEXT+WS_VISIBLE+WS_TABSTOP STYLEDT equ WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_AUTOHSCROLL STYLSTAT equ WS_CHILD+WS_VISIBLE+WS_EX_CLIENTEDGE ; идентификатор стандартной иконки IDI_APPLICATION equ 32512 IDI_WARNING equ 32515 ; идентификатор курсора IDC_ARROW equ 32512 ; режим показа окна - нормальный SW_SHOWNORMAL equ 1 COLOR_BTNFACE equ 15 ;==================================================== ; прототипы внешних процедур ;==================================================== EXTERN SetFocus@4:NEAR EXTERN SendMessageA@16:NEAR EXTERN MessageBoxA@16: NEAR EXTERN CreateWindowExA@48:NEAR EXTERN DefWindowProcA@16:NEAR EXTERN DispatchMessageA@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetMessageA@16:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN LoadCursorA@8:NEAR EXTERN LoadIconA@8:NEAR EXTERN PostQuitMessage@4:NEAR EXTERN RegisterClassA@4:NEAR EXTERN ShowWindow@8:NEAR EXTERN TranslateMessage@4:NEAR EXTERN UpdateWindow@4:NEAR EXTERN GetSystemMetrics@4:NEAR EXTERN CreateFontIndirectA@4:NEAR EXTERN SendMessageA@16:NEAR EXTERN GetWindowTextLengthA@4:NEAR EXTERN GetWindowTextLengthA@4:NEAR ;==================================================== ; директивы компоновщику для подключения библиотек ;==================================================== includelib i:\masm32\lib\user32.lib includelib i:\masm32\lib\kernel32.lib includelib i:\masm32\lib\gdi32.lib ;==================================================== ; структуры ;==================================================== ; ;-------------------- ; структура сообщения ;-------------------- MSGSTRUCT STRUC MSHWND DD ? ; идентификатор окна, ; получающего сообщение MSMESSAGE DD ? ; идентификатор сообщения MSWPARAM DD ? ; доп. информация о сообщении MSLPARAM DD ? ; доп. информация о сообщении MSTIME DD ? ; время посылки сообщения MSPT DD ? ; положение курсора, во время посылки ; сообщения MSGSTRUCT ENDS ;-------------------- ; структура окна ;-------------------- WNDCLASS STRUC CLSSTYLE DD ? ; стиль окна CLWNDPROC DD ? ; указатель на процедуру окна CLSCSEXTRA DD ? ; информация о доп. байтах для ; данной структуры CLWNDEXTRA DD ? ; информация о доп. байтах для окна CLSHINSTANCE DD ? ; дескриптор приложения CLSHICON DD ? ; идентификатор иконы окна CLSHCURSOR DD ? ; идентификатор курсора окна CLBKGROUND DD ? ; идентификатор кисти окна CLMENUNAME DD ? ; имя-идентификатор меню CLNAME DD ? ; специфицирует имя класса окон WNDCLASS ENDS ;-------------------- ; структура шрифта ;-------------------- LOGFONTA STRUCT lfHeight DWORD ? lfWidth DWORD ? lfEscapement DWORD ? lfOrientation DWORD ? lfWeight DWORD ? lfItalic BYTE ? lfUnderline BYTE ? lfStrikeOut BYTE ? lfCharSet BYTE ? lfOutPrecision BYTE ? lfClipPrecision BYTE ? lfQuality BYTE ? lfPitchAndFamily BYTE ? lfFaceName BYTE 'MS Sans Serif',0 LOGFONTA ENDS ;==================================================== ; сегмент данных ;==================================================== _DATA SEGMENT DWORD PUBLIC USE32 'DATA' NEWHWND DD 0 MSG MSGSTRUCT <?> WC WNDCLASS <?> LG LOGFONTA <?> HINST DD 0 ; здесь хранится дескриптор приложения TITLENAME DB 'WinZip 9.0 SR-1 KeyGen',0 CLASSNAME DB 'CLASS32',0 CPBUT DB 'Generate',0 ; выход CPEDT DB ? CPSTAT DB 'Created by Morskoivolk ',0 CPSTAT1 DB 'Enter name:',0 CPSTAT2 DB 'Serial number:',0 CLSBUTN DB 'BUTTON',0 CLSEDIT DB 'EDIT',0 CLSSTAT DB 'STATIC',0 HWNDBTN DWORD 0 HWNDEDT DWORD 0 HWNDEDT1 DWORD 0 HWNDSTAT DWORD 0 HWFONT DWORD 0 HWFONT1 DWORD 0 W DWORD 0 H DWORD 0 X DWORD 0 Y DWORD 0 el_width DWORD 0 Name_length DWORD 0 str1 DB 'Внимание!!!',0 str2 DB 'Введите имя',0 str3 DB 'Минимальная длина имени - 6 символов',0 _DATA ENDS ;==================================================== ; сегмент кода ;==================================================== _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; получить дескриптор приложения PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX REG_CLASS: ; заполнить структуру окна стиль MOV [WC.CLSSTYLE], style ; процедура обработки сообщений MOV [WC.CLWNDPROC], OFFSET WNDPROC MOV [WC.CLSCSEXTRA], 0 MOV [WC.CLWNDEXTRA], 0 MOV EAX, [HINST] MOV [WC.CLSHINSTANCE], EAX ;--------- иконка окна PUSH 1 PUSH [HINST] CALL LoadIconA@8 MOV [WC.CLSHICON], EAX ;---------- курсор окна PUSH IDC_ARROW PUSH 0 CALL LoadCursorA@8 MOV [WC.CLSHCURSOR], EAX ;--------- MOV [WC.CLBKGROUND], COLOR_BTNFACE+1 ; цвет окна MOV DWORD PTR [WC.CLMENUNAME], 0 MOV DWORD PTR [WC.CLNAME], OFFSET CLASSNAME PUSH OFFSET WC CALL RegisterClassA@4 ;Расположение окна приложения в центре экрана mov W,190 mov H,195 push SM_CXSCREEN call GetSystemMetrics@4 PUSH EAX PUSH W call TOPXY mov X,eax push SM_CYSCREEN call GetSystemMetrics@4 PUSH EAX PUSH W call TOPXY mov Y,eax ; создать окно зарегистрированного класса PUSH 0 PUSH [HINST] PUSH 0 PUSH 0 PUSH H ; DY — высота окна PUSH W ; DX - ширина окна PUSH Y ; Y — координата левого верхнего угла PUSH X ; X — координата левого верхнего угла PUSH OFFSET WINDOWSTYLE PUSH OFFSET TITLENAME ; имя окна PUSH OFFSET CLASSNAME ; имя класса PUSH 0 CALL CreateWindowExA@48 ; проверка на ошибку ;CMP EAX, 0 ;JZ _ERR MOV [NEWHWND], EAX ; дескриптор окна ; -------------------------------------------------- PUSH SW_SHOWNORMAL PUSH [NEWHWND] CALL ShowWindow@8; показать созданное окно ; -------------------------------------------------- PUSH [NEWHWND] CALL UpdateWindow@4 ; команда перерисовать видимую ; часть окна, сообщение WM_PAINT ; петля обработки сообщений MSG_LOOP: PUSH 0 PUSH 0 PUSH 0 PUSH offset MSG CALL GetMessageA@16 CMP EAX, 0 JE END_LOOP PUSH offset MSG CALL TranslateMessage@4 PUSH offset MSG CALL DispatchMessageA@4 JMP MSG_LOOP END_LOOP: ; выход из программы (закрыть процесс) PUSH [MSG.MSWPARAM] CALL ExitProcess@4 _ERR: JMP END_LOOP ; -------------------------------------------------- ; WARNING: Win32 requires that EBX, EDI, and ESI be preserved! We comply ; with this by listing those regs after the 'uses' statement in the 'proc' ; line. This allows the Assembler to save them for us. ; процедура окна ; расположение параметров в стеке ; [EBP+014H] LPARAM ; [EBP+10H] WAPARAM ; [EBP+0CH] MES ; [EBP+8] HWND WNDPROC PROC PUSH EBP MOV EBP, ESP PUSH EBX PUSH ESI PUSH EDI CMP DWORD PTR [EBP+0CH], WM_DESTROY JE WMDESTROY CMP DWORD PTR [EBP+0CH], WM_CREATE JE WMCREATE CMP DWORD PTR [EBP+10H], 100 ;если нажата кнопка 'Generete' JE BNCLICKED JMP DEFWNDPROC WMCREATE: ;создание шрифта MS SANS SERIF MOV lg.LfHeight,14 ; высота фонта 14 MOV lg.LfWidth, 0 ; ширина фонта MOV lg.LfEscapement,900 ; ориентация MOV lg.LfOrientation, 0 ; вертикальная MOV lg.LfWeight,900 ; толщина линий шрифта MOV lg.LfItalic, 0 ; курсив MOV lg.LfUnderline, 0 ; подчеркивание MOV lg.LfStrikeOut, 0 ; перечеркивание MOV lg.LfCharSet, 0 ; набор шрифтов MOV lg.LfOutPrecision, 0 MOV lg.LfClipPrecision, 0 MOV lg.LfQuality,2 MOV lg.LfPitchAndFamily,0 PUSH OFFSET lg CALL CreateFontIndirectA@4 mov HWFONT,EAX MOV lg.LfHeight,15 ; высота фонта 15 MOV lg.LfWidth, 0 ; ширина фонта MOV lg.LfEscapement,900 ; ориентация MOV lg.LfOrientation, 0 ; вертикальная MOV lg.LfWeight,0 ; толщина линий шрифта MOV lg.LfItalic, 0 ; курсив MOV lg.LfUnderline, 0 ; подчеркивание MOV lg.LfStrikeOut, 0 ; перечеркивание MOV lg.LfCharSet, 0 ; набор шрифтов MOV lg.LfOutPrecision, 0 MOV lg.LfClipPrecision, 0 MOV lg.LfQuality,2 MOV lg.LfPitchAndFamily,0 PUSH OFFSET lg CALL CreateFontIndirectA@4 MOV HWFONT1,EAX ; создать окно-кнопку mov EBX,W MOV el_width,160 PUSH EBX PUSH el_width call TOPXY SUB EAX,4 ;это чтобы элемент располагался по центру окна mov X,eax PUSH 0 PUSH [HINST] PUSH 100 PUSH DWORD PTR [EBP+08H] PUSH 24 ; DY PUSH el_width ; DX PUSH 125 ; Y PUSH X ; X PUSH STYLBTN PUSH OFFSET CPBUT ; имя окна PUSH OFFSET CLSBUTN ; имя класса PUSH 0 CALL CreateWindowExA@48 MOV HWNDBTN, EAX ; запомнить дескриптор кнопки PUSH 0 PUSH HWFONT1 PUSH WM_SETFONT PUSH HWNDBTN CALL SendMessageA@16 ; создать компенент типа TStatic PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 20 ; DY PUSH 160 ; DX PUSH 150 ; Y PUSH 20 ; X PUSH STYLSTAT PUSH OFFSET CPSTAT ; имя окна PUSH OFFSET CLSSTAT ; имя класса PUSH 0 CALL CreateWindowExA@48 MOV HWNDSTAT,EAX PUSH 0 PUSH HWFONT1 PUSH WM_SETFONT PUSH HWNDSTAT CALL SendMessageA@16 ;создать компенент типа TStatic_1 PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 20 ; DY PUSH 160 ; DX PUSH 2 ; Y PUSH 7 ; X PUSH STYLSTAT PUSH OFFSET CPSTAT1 ; имя окна PUSH OFFSET CLSSTAT ; имя класса PUSH 0 CALL CreateWindowExA@48 MOV HWNDSTAT,EAX PUSH 0 PUSH HWFONT PUSH WM_SETFONT PUSH HWNDSTAT CALL SendMessageA@16 ;создать компенент типа TStatic_2 PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 20 ; DY PUSH 160 ; DX PUSH 47 ; Y PUSH 7 ; X PUSH STYLSTAT PUSH OFFSET CPSTAT2 ; имя окна PUSH OFFSET CLSSTAT ; имя класса PUSH 0 CALL CreateWindowExA@48 MOV HWNDSTAT,EAX PUSH 0 PUSH HWFONT PUSH WM_SETFONT PUSH HWNDSTAT CALL SendMessageA@16 ; создать окно редактирования_1 mov EBX,W MOV el_width,160 PUSH EBX PUSH el_width call TOPXY SUB EAX,4 mov X,eax PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 23 ; DY PUSH el_width ; DX PUSH 20 ; Y PUSH X ; X PUSH STYLEDT PUSH OFFSET CPEDT ; имя окна PUSH OFFSET CLSEDIT ; имя класса PUSH WS_EX_CLIENTEDGE CALL CreateWindowExA@48 MOV HWNDEDT,EAX PUSH 0 PUSH HWFONT1 PUSH WM_SETFONT PUSH HWNDEDT CALL SendMessageA@16 ;--------- установить фокус на окне редактирования PUSH HWNDEDT CALL SetFocus@4 ; создать окно редактирования_2 mov EBX,W MOV el_width,160 PUSH EBX PUSH el_width call TOPXY SUB EAX,4 mov X,eax PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 23 ; DY PUSH el_width ; DX PUSH 65 ; Y PUSH X ; X PUSH STYLEDT PUSH OFFSET CPEDT ; имя окна PUSH OFFSET CLSEDIT ; имя класса PUSH WS_EX_CLIENTEDGE CALL CreateWindowExA@48 MOV HWNDEDT1,EAX PUSH 0 PUSH HWFONT1 PUSH WM_SETFONT PUSH HWNDEDT1 CALL SendMessageA@16 MOV EAX, 0 JMP FINISH DEFWNDPROC: PUSH DWORD PTR [EBP+14H] PUSH DWORD PTR [EBP+10H] PUSH DWORD PTR [EBP+0CH] PUSH DWORD PTR [EBP+08H] CALL DefWindowProcA@16 JMP FINISH BNCLICKED: PUSH HWNDEDT call GetWindowTextLengthA@4 ;считает количество символов во введенном тексте .if EAX==0 ;если количество символов 0, то call EnterName ;вывод сообщения.... .elseif EAX<6 ;если количество символов < 6, то call MinLength ;вывод сообщения.... .endif JMP FINISH WMDESTROY: PUSH 0 CALL PostQuitMessage@4 ; сообщение WM_QUIT MOV EAX, 0 FINISH: POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP ;------------------------------------------------------------ TopXY proc wDim:DWORD, sDim:DWORD ;процедура,центрирующая окно приложения shr sDim,1 shr wDim,1 mov eax,wDim sub sDim,eax mov eax,SDim ret TopXY endp ;=========================================================== ;процедуры вывода сообщения о некорректном вводе информации ;=========================================================== EnterName proc push 0 push offset str1 push offset str2 push NEWHWND call MessageBoxA@16 RET EnterName endp MinLength proc push 0 push offset str1 push offset str3 push NEWHWND call MessageBoxA@16 RET MinLength endp ;=========================================================== _TEXT ENDS END START
круто. 4 кб кода нейзвестно зачем писать. PUSH 0 PUSH [HINST] PUSH 0 PUSH 0 PUSH H ; DY — высота окна PUSH W ; DX - ширина окна PUSH Y ; Y — координата левого верхнего угла PUSH X ; X — координата левого верхнего угла PUSH OFFSET WINDOWSTYLE PUSH OFFSET TITLENAME ; имя окна PUSH OFFSET CLASSNAME ; имя класса PUSH 0 CALL CreateWindowExA@48 Замени все push 0 на xor reg,reg push reg уже меньше будет
но ведь reg придется объявлять в сегменте данных как тип DWORD....это же дополнительно место занимает, или я не прав?
Всё как будто списано с учебника для начинающих. Пример субоптимальности налицо. (MOV EAX, 0). Даже компайлер-программа-не позволила б себе такого.
Я даже знаю как ты определил, что она весит 4 096 байт ))))))))))))))))))))) Интересно, у кого будет весить меньше?))))
Если откомпилировать этот же код с опцией ALIGN:4, то размер exe-шника уже уменьшится до 2.9 КБ А по поводу оптимизации: 1) естественно, заменить всякие mov X, 0 и push 0 2) код, который создает окно (особенно контролы), почти одинаковый - его лучше выделить в отдельную процедуру.
я тока постигаю Ассм....поэтому не надо так категорично , вспомните себя....))) ужасно хочется писать на ассме не просто проги, а действительно хорошие приложения (небольшие). так что не вижу ничего страшного что основа примера была взята из тупых банальных учебников, которые не всегда хорошие и понятные,....но все таки с чего то надо начинать. Так что прошу побольше замечаний делать по теме, а не ходить вокруг да около и высмеивать, то с чего вы начинали сами...
у отстрелянов процесоров интела проблем оптимизации ето проблем мира.у хорошие процесоров таких проблемов не стоит - у они хардуер поимает и придуман работои с очен долгих слов исполнят команди на асемблере високом уровне ,там не нужно такая плохая ос как вин где с C++ заменяется нужние хардуерние команди .потом и ос написана плохо.Интелские консерви не смогут 2 чисел собираут без ошибки а как надеятся на их въичислит кодов и другие ? Система командов неортогоналная и плохая, морално и психо остарела как бабушка у асм програмированиу. 4 регистер не достато4ни дори у треторазряднъих компутеров , у новъих добавлени 32 хахахахахах, у Атмела 8 бит имеет 256 из 6 года назад ихаааааааааа.я у моем микропроцесорнъх систем пуш и поп никогда не ползовал,и регистри не сохранял в лудост как туда. мои девиз - стреляи у интел и маикрософта.
Morskoivolk Ну какой смысл пытаться оптимизировать на асме код, состоящий из вызовов API? Шансов переплюнуть хороший компилятор (типа VC++) практически нет - ни по скорости, ни по размеру. Да и радости, IMHO, никакой... Разве что поучиться. Вот процедура генерации серийника - другое дело.
вот именно поучиться и хочется, чтобы в дальнейшем не грузить голову по этому поводу. процедура генерации серийника.....не сказал бы что там уж много наоптимизируешь....хотя если она большая, и много в ней всякой лажи..то конечно. в любом случае, неужели ни у кого не возникала идея написать своего рода шапку, к примеру, для окна с двумя полями ввода, кнопкой парой статических элементов, оптимизировать ее скажем до 1 Кб.......а в адльнейшем просто навешивать свои процедуры и функции...например ту же процедуру генерации серийника. Ведь зачем каждый раз тратить силы на уменьшение размера всей программы, когда можно оптимизировать только отдельные пользовательские процедуры?
Слушай конечно всё это уже давно всеми избитые темы. Ознакомся что-ли с сайтом, разделом, неофиту, загляни в инструменты..
Morskoivolk тебе уже отвечали, что конкретно читать в твоем предыдущем посте как под структуру типа MSG выделить строго определенное количество байт даже если твой исходник прогнать через переделанный PoLink (как, читай сам) размер exe упададет с 4к до 2,5к, а твой код еще оптимизировать и оптимизировать, только делай это сам, минимальный размер PE-файла 97 байт, стремись к этому! А Edit'ы, кнопки, статический текст сделать через редактор ресурсов не судьба видимо? orbb Это сербский или болгарский язык?
green А rtl как же. Можно конечно сделать свой rtl, но этож гемор, да и то нет гарантий что прокатит. Лично я маленькие гуёвые проги пишу именно на асме. Нафига мне лишние 50-100кб, скорость разработки конечно немного увеличивается, но чтож делать за всё надо платить. С другой стороны сильно уменьшать размер (до 1-2 кб) тоже смысла не вижу, выравнивание не просто так сделано.
Booster На С++ можно писать без RTL. Я небольшие проги, как правило, так и пишу. Размер получается вполне "асмовский".