возникла небольшая проблема с метками Код (Text): .386 .model flat, stdcall includelib \masm32\lib\user32.lib include \masm32\include\user32.inc .code p1 proc jmp m1; тут проблема m2: jmp m2 m1: ret p1 endp start: call p1 m1: invoke MessageBoxA, 0, 0, 0, 0 ret end start по логике прога должна показать сообщение и завершиться, но почемуто jmp m1 в p1 прыгает на метку m1 в осн. части, и поэтому показываются 2 сообщения. подскажите пожалуйста, с чем это связано?
EFiR, если убрать или переименовать метку в start, то переходит правильно. можно ли как-то указать компилятору искать метки в первую очередь внутри процедуры, чтобы не получалось таких ситуаций? Asterix, да, это я понял, интересовал именно момент с неправильной меткой
и еще одна странность, если в коде закомментить строки m2: jmp m2 прога работает правильно, хотя, метка m2 вроде никак не влияет на m1
Особо не вник в ответы, теперь моя версия . Все метки которые идут от start: end start это глобальные метки на которые можна совершить переход из любой процедуры или функции все что находится внутри p1 proc p1 endp это локальные метки на которые можна совершить переход только внутри данной процедуры. Вообще масм должен выдать сообщение о пересечении имен в такой ситуации. Потомучто если есть глобальная метка локальную с такимже именем создавать нельзя. Вот тут и ошибка что козда из под прок идет jmp m1 мы попадаем на м1 в start: а не в p1. Т.к. у обоих процедур одинаковые прологи код отрабатывает корректно.
PaCHER вроде не совсем так, все метки глобальные по умолчанию. Надо юзать Option Scoped, тогда компилер распознает локальные метки, а внутри деректив proc после меток ставить двоеточие, так распознаются глобальные.
Код (Text): .text:00000000 public _p1@0 .text:00000000 _p1@0 proc near ; CODE XREF: p2()p .text:00000000 ; DATA XREF: p2()+7o ... .text:00000000 jmp short $+2 .text:00000002 retn .text:00000002 _p1@0 endp .text:00000002 .text:00000003 .text:00000003 ; =============== S U B R O U T I N E ======================================= .text:00000003 .text:00000003 .text:00000003 ; int __stdcall p2() .text:00000003 public _p2@0 .text:00000003 _p2@0 proc near .text:00000003 call _p1@0 ; _start .text:00000008 push 0 ; uType .text:0000000A push offset _p1@0 ; lpCaption .text:0000000C push offset _p1@0 ; lpText .text:0000000E push offset _p1@0 ; hWnd .text:00000010 call _MessageBoxA@16 ; MessageBoxA(x,x,x,x) .text:00000015 retn .text:00000015 _p2@0 endp если задизасмить то все понятно становится
копните опции масма касаемо области действия вам надо установить локальную видимость - все будет тип топ
EFiR Внутри прок все метки локальные по умолчанию. Т.к. ты можно создать 10 процедур с одинаковыми метками внутри, и все будет работать и адресоваться правильно.
Ну покрайней мере в 9м масме по умолчанию, может там уже прописаны настройки. NuMeR Когда чтото непонятно смотри в дебагере, а не подбирай результат методом правки исходника и вопросами.
НЕ УВЕРЕН все метки с одинарными двоеточиями или глобальные или локальные - в данном случае вообще дурной тон - нельзя использовать имя в качестве глобального если оно уже локальное и наоборот
так я и смотрел в дебаггере, там увидел, что прыжок делается не на нужный адрес, а если убрать те две комманды, то адрес правильный, но как эти две команды на это влияют мне до сих пор непонятно
NuMeR да действительно, компилер с этими двумя строками подставляет дальнюю метку, а без них ближнюю. а вот по какой причине хез
Clerk все метки с одинарными двоеточиями или глобальные или локальные с двойным двоеточием как и с директивой label все ясно афаик нужно поставить в начале опшон скопед или опшон ноускопед - не помню и справки под рукой нет от масма
option scoped по умолчанию, и метки локальные в этом случае, как и сказал PaCHER. NoScoped делает все метки глобальными, использование :: становится ненужным. Тут у топикстартера другой вопрос. Я тоже немогу понять логику работы компилера в данном случае. вот в этом коде Код (Text): p1 proc jmp m1; тут проблема m2: jmp m2 m1: ret p1 endp start: call p1 m1: invoke MessageBoxA, 0, 0, 0, 0 ret end start компилер в команде jmp m1 подставит адрес m1 которая идет второй по коду, если же после m2 поставить ::(или вообще убрать, что и делает ТС) то в jmp m1 он подставит адрес m1 которая первая по коду, тоесть внутри proc endp. Кто-то может объяснить баг это или фишка.