вопрос по локальным и глобальным переменным...

Тема в разделе "WASM.BEGINNERS", создана пользователем elestrago, 5 июн 2009.

  1. elestrago

    elestrago New Member

    Публикаций:
    0
    Регистрация:
    25 янв 2009
    Сообщения:
    56
    у меня возникла проблема при использовании локальных переменных вместо глобальных

    Когда я создаю просто пустое окно с использованием глобальных переменных то оно создается на ура... а вот с локальными переменными все иначе!

    вот код и еще в атаче 2 ехешника, один там где я использую локальные другой с глабальными переменными..

    Код (Text):
    1. .386
    2. .model FLAT, stdcall
    3. option Casemap:none
    4.  
    5. include D:\masm32\include\windows.inc
    6.  
    7. includelib D:\masm32\lib\user32.lib
    8. includelib D:\masm32\lib\kernel32.lib
    9.  
    10. include Procedure.Inc
    11.  
    12. .data
    13.     MainClassName                          db 'MyClass',0
    14.    
    15. .data?
    16.     hInst                       dd ?
    17.     hWin                        dd ?
    18.     msg                     MSG <?>
    19.     wc                      WNDCLASSEX <?>
    20.  
    21.  
    22. .code
    23. START:
    24.     pus     0
    25.     call        GetModuleHandleA@4
    26.     mov     hInst,eax
    27.    
    28.     call        Main
    29.  
    30.     push        0
    31.     call        ExitProcess@4
    32.    
    33. Main    proc
    34. ;local  wc:WNDCLASSEX    ; вот собственно попытка обьявления локальных переменных...
    35. ;local  msg:MSG
    36.  
    37.     mov     wc.cbSize,sizeof WNDCLASSEX
    38.     mov     wc.style,FALSE
    39.     mov     wc.lpfnWndProc,offset MainProc
    40.     mov     wc.cbWndExtra,0
    41.     mov     wc.cbClsExtra,0
    42.     mov     eax,hInst
    43.     mov     wc.hInstance,eax
    44.  
    45.     push        IDI_APPLICATION
    46.     push        0
    47.     call        LoadIconA@8
    48.     mov     wc.hIcon, eax  
    49.     mov     wc.hIconSm,eax
    50.    
    51.     push        IDC_ARROW
    52.     push        0
    53.     call        LoadCursorA@8
    54.     mov     wc.hCursor,eax
    55.    
    56.     mov     wc.hbrBackground,COLOR_BTNFACE+1
    57.     mov     wc.lpszMenuName,0
    58.     mov     wc.lpszClassName,offset MainClassName
    59.    
    60.     push        offset wc
    61.     call        RegisterClassExA@4 
    62.    
    63.    
    64.     push        0
    65.     push        hInst
    66.     push        0
    67.     push        0
    68.     push        690
    69.     push        1150
    70.     push        100
    71.     push        100
    72.     push        WS_OVERLAPPEDWINDOW  or WS_CLIPCHILDREN or WS_CLIPSIBLINGS
    73.     push        offset MainClassName
    74.  
    75.     push        offset MainClassName
    76.     push        WS_EX_WINDOWEDGE
    77.     call        CreateWindowExA@48 
    78.     mov     hWin,eax
    79.    
    80.     push        SW_SHOWNORMAL
    81.     push        hWin
    82.     call        ShowWindow@8
    83.  
    84.     push        hWin
    85.     call        UpdateWindow@4 
    86.    
    87. MSG_LOOP:
    88.     push        0
    89.     push        0
    90.     push        0
    91.     push        offset msg
    92.     call        GetMessageA@16
    93.     cmp     eax, 0
    94.     je      ExitProgramm
    95.    
    96.     push        offset msg
    97.     call        TranslateMessage@4
    98.    
    99.     push        offset msg
    100.     call        DispatchMessageA@4
    101.    
    102.     jmp     MSG_LOOP
    103. ExitProgramm:
    104.     Ret
    105. Main EndP  
    106.  
    107. MainProc    proc
    108.     push        ebp
    109.     mov     ebp, esp
    110.     push        ebx
    111.     push        esi
    112.     push        edi
    113.     cmp     DWORD PTR [EBP+0CH],WM_DESTROY
    114.     je      WMDESTROY
    115.     cmp     DWORD PTR [EBP+0CH],WM_CREATE
    116.     je      WMCREATE
    117.     cmp     DWORD PTR [EBP+0CH],WM_COMMAND
    118.     je      WMCOMMAND
    119.     cmp     DWORD PTR [EBP+0CH],WM_SIZE
    120.     je      WMSIZE
    121.     jmp     DEFWNDPROC
    122. WMCREATE:
    123.     jmp     DEFWNDPROC
    124. WMSIZE:
    125.     jmp     DEFWNDPROC
    126. WMCOMMAND:
    127.     jmp         DEFWNDPROC
    128. WMDESTROY:
    129.     push        0
    130.     call        PostQuitMessage@4
    131.     mov     eax,0
    132. DEFWNDPROC:
    133.     push        dword ptr [EBP+14H]
    134.     push        dword ptr [EBP+10H]
    135.     push        dword ptr [EBP+0CH]
    136.     push        dword ptr [EBP+08H]
    137.     call        DefWindowProcA@16
    138.     jmp     FINISH
    139. FINISH:
    140.     pop     edi
    141.     pop     esi
    142.     pop     ebx
    143.     pop     ebp
    144.     RET     16
    145. MainProc EndP
    146.  
    147. END START
     
  2. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    Для локальных переменных это неприемлемо. Оффсет вычисляется на стадии компиляции (или компоновки? ну не суть в данном случае важно). А реальный адрес локальной переменной - это что-то в стеке, и фиг знает по какому адресу вообще. Поэтому... надо получать этот указатель через
    lea eax, [name]
    и потом
    push eax
    Можно извратится, понять, что такое локальные переменные на низком уровне, и вычислять этот адрес по другому. Можно - даже через esp, не обязательно только на ebp останавливаться... Но как не крути, одной командой push адрес локальной переменной в стек убрать не получится
     
  3. elestrago

    elestrago New Member

    Публикаций:
    0
    Регистрация:
    25 янв 2009
    Сообщения:
    56
    я знаю что оффсет не катит :) компилятор сам не даст скомпилить такой код, а код выше преведенный заточен под использование глобальных переменных
     
  4. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    Кхм... Я не знаю, что подо что у тебя заточено, но экзешник с локальными переменными использует
    Код (Text):
    1. ...
    2. 0040106A  | C745 F0 100000>MOV [LOCAL.4],10
    3. 00401071  | C745 F4 000000>MOV [LOCAL.3],0
    4. 00401078  | C745 F8 003040>MOV [LOCAL.2],LOCAL.00403000             ;  ASCII "MyClass"
    5. 0040107F  | 66:FF75 D0        PUSH WORD PTR SS:[EBP-30]                 ; /pWndClassEx = 00000030
    6. 00401083  | E8 DC000000      CALL <JMP.&user32.RegisterClassExA>      ; \RegisterClassExA
    7. ...
    какой-то бред вместо правильного указателя. В masm32 используется макрос ADDR для этого. Если хочешь все руками, то пишешь как я сказал. Но не так, как у тебя. Исходник с локальными переменными покажи. Не надо весь - только две строчки, как ты передаешь параметр и вызываешь RegisterClassEx.
     
  5. elestrago

    elestrago New Member

    Публикаций:
    0
    Регистрация:
    25 янв 2009
    Сообщения:
    56
    Код (Text):
    1. Main    proc
    2. local   wc:WNDCLASSEX
    3. local   msg:MSG
    4. ......
    5.     mov     wc.cbSize,sizeof WNDCLASSEX
    6.     mov     wc.style,FALSE
    7.     mov     wc.lpfnWndProc,offset MainProc
    8. .......
    9.     push        wc
    10.     call        RegisterClassExA@4
     
  6. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    Я может непонятно первый пост написал?
    Короче, addr поставь перед wc, и будет все как надо.
     
  7. elestrago

    elestrago New Member

    Публикаций:
    0
    Регистрация:
    25 янв 2009
    Сообщения:
    56
    FatMoon Спасибо тебе огромное :) все заработало!!
    Тема закрыта!
     
  8. PaCHER

    PaCHER New Member

    Публикаций:
    0
    Регистрация:
    25 мар 2006
    Сообщения:
    852
    Еще незабудь во все локальные переменные занести нужные значения а остальные обнулить что касается и структур, иначе могут быть смены стиля окна при каждом создании.
     
  9. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    ...и естественно, точно также везде, где пытаешься передать адрес локальной переменной. msg, к примеру...

    Так, в качестве отступления от темы:
    Любители высокоуровневого языка пропагандируют локальные переменные как единственно верную затею, для вызова процедур. Дескать, локальные переменные не используют память, локальные переменные экономят место на диске, локальные переменные - это супер! А глобальные - только там, где надо иметь общую для нескольких процедур переменную, тут уж не обойтись.
    Но IMHO, для ассемблера надо смотреть, что и как ты вызываешь. Если основная работа с переменными - запись и чтение ЗНАЧЕНИЙ, то локальные являются оптимумом, везде, где не требуются глобальные. Если основная работа с переменными - передача указателя на них в процедуру, то наплевать, что там кто говорит, оптимум использование глобальной переменной, и точка. К примеру, делать в твоем случае локальную msg - полный абсурд. Глобальной она займет гораздо меньше кода. А вот wc как раз нормально локальной - обращение к объектам структуры в локальной переменной - оптимально по размеру, скорости и здравому смыслу. (За исключением случая, когда структура может быть заполнена при компиляции, константами)