у меня возникла проблема при использовании локальных переменных вместо глобальных Когда я создаю просто пустое окно с использованием глобальных переменных то оно создается на ура... а вот с локальными переменными все иначе! вот код и еще в атаче 2 ехешника, один там где я использую локальные другой с глабальными переменными.. Код (Text): .386 .model FLAT, stdcall option Casemap:none include D:\masm32\include\windows.inc includelib D:\masm32\lib\user32.lib includelib D:\masm32\lib\kernel32.lib include Procedure.Inc .data MainClassName db 'MyClass',0 .data? hInst dd ? hWin dd ? msg MSG <?> wc WNDCLASSEX <?> .code START: pus 0 call GetModuleHandleA@4 mov hInst,eax call Main push 0 call ExitProcess@4 Main proc ;local wc:WNDCLASSEX ; вот собственно попытка обьявления локальных переменных... ;local msg:MSG mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,FALSE mov wc.lpfnWndProc,offset MainProc mov wc.cbWndExtra,0 mov wc.cbClsExtra,0 mov eax,hInst mov wc.hInstance,eax push IDI_APPLICATION push 0 call LoadIconA@8 mov wc.hIcon, eax mov wc.hIconSm,eax push IDC_ARROW push 0 call LoadCursorA@8 mov wc.hCursor,eax mov wc.hbrBackground,COLOR_BTNFACE+1 mov wc.lpszMenuName,0 mov wc.lpszClassName,offset MainClassName push offset wc call RegisterClassExA@4 push 0 push hInst push 0 push 0 push 690 push 1150 push 100 push 100 push WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS push offset MainClassName push offset MainClassName push WS_EX_WINDOWEDGE call CreateWindowExA@48 mov hWin,eax push SW_SHOWNORMAL push hWin call ShowWindow@8 push hWin call UpdateWindow@4 MSG_LOOP: push 0 push 0 push 0 push offset msg call GetMessageA@16 cmp eax, 0 je ExitProgramm push offset msg call TranslateMessage@4 push offset msg call DispatchMessageA@4 jmp MSG_LOOP ExitProgramm: Ret Main EndP MainProc 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+0CH],WM_COMMAND je WMCOMMAND cmp DWORD PTR [EBP+0CH],WM_SIZE je WMSIZE jmp DEFWNDPROC WMCREATE: jmp DEFWNDPROC WMSIZE: jmp DEFWNDPROC WMCOMMAND: jmp DEFWNDPROC WMDESTROY: push 0 call PostQuitMessage@4 mov eax,0 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 FINISH: pop edi pop esi pop ebx pop ebp RET 16 MainProc EndP END START
Для локальных переменных это неприемлемо. Оффсет вычисляется на стадии компиляции (или компоновки? ну не суть в данном случае важно). А реальный адрес локальной переменной - это что-то в стеке, и фиг знает по какому адресу вообще. Поэтому... надо получать этот указатель через lea eax, [name] и потом push eax Можно извратится, понять, что такое локальные переменные на низком уровне, и вычислять этот адрес по другому. Можно - даже через esp, не обязательно только на ebp останавливаться... Но как не крути, одной командой push адрес локальной переменной в стек убрать не получится
я знаю что оффсет не катит компилятор сам не даст скомпилить такой код, а код выше преведенный заточен под использование глобальных переменных
Кхм... Я не знаю, что подо что у тебя заточено, но экзешник с локальными переменными использует Код (Text): ... 0040106A | C745 F0 100000>MOV [LOCAL.4],10 00401071 | C745 F4 000000>MOV [LOCAL.3],0 00401078 | C745 F8 003040>MOV [LOCAL.2],LOCAL.00403000 ; ASCII "MyClass" 0040107F | 66:FF75 D0 PUSH WORD PTR SS:[EBP-30] ; /pWndClassEx = 00000030 00401083 | E8 DC000000 CALL <JMP.&user32.RegisterClassExA> ; \RegisterClassExA ... какой-то бред вместо правильного указателя. В masm32 используется макрос ADDR для этого. Если хочешь все руками, то пишешь как я сказал. Но не так, как у тебя. Исходник с локальными переменными покажи. Не надо весь - только две строчки, как ты передаешь параметр и вызываешь RegisterClassEx.
Код (Text): Main proc local wc:WNDCLASSEX local msg:MSG ...... mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,FALSE mov wc.lpfnWndProc,offset MainProc ....... push wc call RegisterClassExA@4
Еще незабудь во все локальные переменные занести нужные значения а остальные обнулить что касается и структур, иначе могут быть смены стиля окна при каждом создании.
...и естественно, точно также везде, где пытаешься передать адрес локальной переменной. msg, к примеру... Так, в качестве отступления от темы: Любители высокоуровневого языка пропагандируют локальные переменные как единственно верную затею, для вызова процедур. Дескать, локальные переменные не используют память, локальные переменные экономят место на диске, локальные переменные - это супер! А глобальные - только там, где надо иметь общую для нескольких процедур переменную, тут уж не обойтись. Но IMHO, для ассемблера надо смотреть, что и как ты вызываешь. Если основная работа с переменными - запись и чтение ЗНАЧЕНИЙ, то локальные являются оптимумом, везде, где не требуются глобальные. Если основная работа с переменными - передача указателя на них в процедуру, то наплевать, что там кто говорит, оптимум использование глобальной переменной, и точка. К примеру, делать в твоем случае локальную msg - полный абсурд. Глобальной она займет гораздо меньше кода. А вот wc как раз нормально локальной - обращение к объектам структуры в локальной переменной - оптимально по размеру, скорости и здравому смыслу. (За исключением случая, когда структура может быть заполнена при компиляции, константами)