проблема с метками(масм)

Тема в разделе "WASM.BEGINNERS", создана пользователем NuMeR, 24 фев 2010.

  1. NuMeR

    NuMeR New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2010
    Сообщения:
    6
    возникла небольшая проблема с метками
    Код (Text):
    1. .386
    2. .model flat, stdcall
    3.  
    4. includelib \masm32\lib\user32.lib
    5. include    \masm32\include\user32.inc
    6.  
    7. .code
    8.  
    9. p1 proc
    10.   jmp m1; тут проблема
    11.     m2:
    12.     jmp m2
    13.   m1:
    14.   ret
    15. p1 endp
    16.  
    17. start:
    18.   call p1
    19.   m1:
    20.   invoke MessageBoxA, 0, 0, 0, 0
    21.   ret
    22. end start
    по логике прога должна показать сообщение и завершиться, но почемуто jmp m1 в p1 прыгает на метку m1 в осн. части, и поэтому показываются 2 сообщения.
    подскажите пожалуйста, с чем это связано?
     
  2. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    потому что до метки m1 в proc компилер еще не дошел
     
  3. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    это связано с ret после MessageBox и с адресом возврата из call на стеке в этот момент
     
  4. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    блин, бред написал, связано с тем что компилер адрес метки переписал когда ее встретил второй раз
     
  5. NuMeR

    NuMeR New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2010
    Сообщения:
    6
    EFiR, если убрать или переименовать метку в start, то переходит правильно. можно ли как-то указать компилятору искать метки в первую очередь внутри процедуры, чтобы не получалось таких ситуаций?
    Asterix, да, это я понял, интересовал именно момент с неправильной меткой
     
  6. NuMeR

    NuMeR New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2010
    Сообщения:
    6
    и еще одна странность, если в коде закомментить строки

    m2:
    jmp m2

    прога работает правильно, хотя, метка m2 вроде никак не влияет на m1
     
  7. PaCHER

    PaCHER New Member

    Публикаций:
    0
    Регистрация:
    25 мар 2006
    Сообщения:
    852
    Особо не вник в ответы, теперь моя версия :).
    Все метки которые идут от
    start:
    end start
    это глобальные метки на которые можна совершить переход из любой процедуры или функции

    все что находится внутри
    p1 proc
    p1 endp
    это локальные метки на которые можна совершить переход только внутри данной процедуры. Вообще масм должен выдать сообщение о пересечении имен в такой ситуации. Потомучто если есть глобальная метка локальную с такимже именем создавать нельзя.

    Вот тут и ошибка что козда из под прок идет jmp m1 мы попадаем на м1 в start: а не в p1. Т.к. у обоих процедур одинаковые прологи код отрабатывает корректно.
     
  8. NuMeR

    NuMeR New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2010
    Сообщения:
    6
    но все таки непонятно, почему если убрать строки

    m2:
    jmp m2

    прога работает правильно
     
  9. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    PaCHER
    вроде не совсем так, все метки глобальные по умолчанию. Надо юзать Option Scoped, тогда компилер распознает локальные метки, а внутри деректив proc после меток ставить двоеточие, так распознаются глобальные.
     
  10. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    Код (Text):
    1. .text:00000000                 public _p1@0
    2. .text:00000000 _p1@0       proc near                ; CODE XREF: p2()p
    3. .text:00000000                                             ; DATA XREF: p2()+7o ...
    4.  
    5. .text:00000000                 jmp     short $+2
    6. .text:00000002                 retn
    7.  
    8. .text:00000002 _p1@0       endp
    9. .text:00000002
    10. .text:00000003
    11. .text:00000003 ; =============== S U B R O U T I N E =======================================
    12. .text:00000003
    13. .text:00000003
    14. .text:00000003 ; int __stdcall p2()
    15. .text:00000003                 public _p2@0
    16. .text:00000003 _p2@0       proc near
    17.  
    18. .text:00000003                 call    _p1@0           ; _start
    19. .text:00000008                 push    0               ; uType
    20. .text:0000000A                 push    offset _p1@0    ; lpCaption
    21. .text:0000000C                 push    offset _p1@0    ; lpText
    22. .text:0000000E                 push    offset _p1@0    ; hWnd
    23. .text:00000010                 call    _MessageBoxA@16 ; MessageBoxA(x,x,x,x)
    24. .text:00000015                 retn
    25.  
    26. .text:00000015 _p2@0           endp
    если задизасмить то все понятно становится
     
  11. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    я тут хотел сказать два двоеточия
     
  12. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    копните опции масма касаемо области действия вам надо установить локальную видимость - все будет тип топ
     
  13. PaCHER

    PaCHER New Member

    Публикаций:
    0
    Регистрация:
    25 мар 2006
    Сообщения:
    852
    EFiR
    Внутри прок все метки локальные по умолчанию. Т.к. ты можно создать 10 процедур с одинаковыми метками внутри, и все будет работать и адресоваться правильно.
     
  14. PaCHER

    PaCHER New Member

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

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    НЕ УВЕРЕН
    все метки с одинарными двоеточиями или глобальные или локальные - в данном случае вообще дурной тон - нельзя использовать имя в качестве глобального если оно уже локальное и наоборот
     
  16. NuMeR

    NuMeR New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2010
    Сообщения:
    6
    так я и смотрел в дебаггере, там увидел, что прыжок делается не на нужный адрес, а если убрать те две комманды, то адрес правильный, но как эти две команды на это влияют мне до сих пор непонятно
     
  17. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    NuMeR
    да действительно, компилер с этими двумя строками подставляет дальнюю метку, а без них ближнюю. а вот по какой причине хез
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Rockphorr
    Label::
     
  19. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    Clerk
    все метки с одинарными двоеточиями или глобальные или локальные
    с двойным двоеточием как и с директивой label все ясно

    афаик нужно поставить в начале опшон скопед или опшон ноускопед - не помню и справки под рукой нет от масма
     
  20. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    option scoped по умолчанию, и метки локальные в этом случае, как и сказал PaCHER. NoScoped делает все метки глобальными, использование :: становится ненужным.

    Тут у топикстартера другой вопрос. Я тоже немогу понять логику работы компилера в данном случае.

    вот в этом коде

    Код (Text):
    1. p1 proc
    2.   jmp m1; тут проблема
    3.     m2:
    4.     jmp m2
    5.   m1:
    6.   ret
    7. p1 endp
    8.  
    9. start:
    10.   call p1
    11.   m1:
    12.   invoke MessageBoxA, 0, 0, 0, 0
    13.   ret
    14. end start
    компилер в команде jmp m1 подставит адрес m1 которая идет второй по коду, если же после m2 поставить ::(или вообще убрать, что и делает ТС) то в jmp m1 он подставит адрес m1 которая первая по коду, тоесть внутри proc endp. Кто-то может объяснить баг это или фишка.