забыл я года два назад мне это надо было сделать (сделал на TASM вроде бы...), уже не помню как именно это делается, и литература вся ушла в *опу сейчас пишу процедуру, в определенном месте которой мне нужно сделать переход на определенный адрес программы, причем этот адрес находится вне моей процедуры., адрес относительно начала процедуры знаю точно я предполагал сделать это так: получить eip; вычесть из него определенное число; jmp на полученный адрес... возникла проблема: не помню как можно получить этот eip. голове крутится "через стек" а как хз. пишу на MSVC 2005 ассемблерную вставку. push eip оно мне выдает андекларед идентифаер помогите пожалуйста
собственно говоря боюсь это не подойдет. компилятор вставляет вместо метки относительный адресс если я не ошибаюсь а мне нужен полностью базонезависимый код, т.е. мне нужен переход скажем на 100 байтов назад, вот таким образом как получить адресс на 100 байтов назад не подскажите? вот к примеру процедурка: Код (Text): ..... some code ...... //в EBX нао поместить адрес начала этого кода. т.е. адрес текущей команды push ebx; //он сохраняется, дальше надо еще раз его использовать mov eax,0xffffffff; mov edx,0xffffffff; mov ecx,eax; sub ebx,eax; M1: //вот здесь аналогичная проблема. переход нужен относительный // а я не знаю шо подставит сюда компиллер mov eax,[ebx]; xor eax,edx; mov [ebx],eax; add ebx,1; dec ecx; jnz M1; //вернее компиллер подставит это сюда pop ebx; mov eax,0xffffffff; sub ebx,eax; //вычисляем адрес перехода jmp ebx; //переходим (переход осуществляется за пределы процедуры - назад до ее начала в мое частном случае) ret; помогите пожалуйста. боюсь гуглить я это буду намного дольше чем у меня есть времени
в том то и дело что я не знаю где этот код будет размещен. и offset MyProc никак нельзя получить с этим бы я справился
someone Смотрим описание команд, дисасм листинг и т.д. А так же разберись что такое относительный и абсолютный переходы. Ищем на сайте про дельта смещение.
с дельта смещением и так все понятно. нужно получить текущий адрес, и отнять/прибавить от него дельту проблема в том как его получить (текущий адрес). я вообщето допустил возможность существования относительной команды перехода (или команды относительного перехода?) на Х байт назад/вперед угу, смотрим, но потому как времени у меня, к сожалению, очень мало, я параллельно поглядываю и сюда, а вдруг найдется добрый кодер, который знает и подскажет? гм. мне как раз нужен относительный переход (я это так понимаю: переход относительно текущей позиции) абсолютный переход: переход на конкретный адрес. я хочу получить абсолютный адрес путем получения текущего адреса и арифметических операций с дельтой. PS: просто с ассемблером работаю мало, в основном СИ, а тут ну не вижу я других вариантов решения проблемы кроме как накодить на ассемблере потому сейчас и занялся быстрым вспоминанием ассемблера, и т.д.
вообще в этом случае можно сделать без проще. mov eax, a1; если я не ошибаюсь будет то же самое. хотя может я всетаки ошибаюсь? в общем мне кажется что это не подходит.
someone mov eax, offset a1 даст тот же результат, если кто-нибудь(система в большинстве случаев) позаботится о том, чтобы эта команда дала правильный результат. В то время как call/pop ни от кого не зависит
someone Конечно ошибаешься, т.к. mov eax,offset a1 загрузит в eax адрес метки a1 в твоем исходном скомпилированном коде, но если ты в рантайме переместишь это кусок кода по другому адресу, то адрес метки a1 изменится и значение в eax будет неверным. А вот call выполняется процессором именно в рантайме и помещает в стек всегда текущее значение адреса возврата независимо от базы или чего то еще Если кажется - креститься надо Код, приведенный asd это классика. Из других способов - только модификация кода, т.е. ручная замена всех абсолютных адресов в куске кода (коррекция релоков)
Код (Text): ..... some code ...... call a1 a1: pop ebx; //в EBX нао поместить адрес начала этого кода. т.е. адрес текущей команды push ebx; //он сохраняется, дальше надо еще раз его использовать mov eax,0xffffffff; mov edx,0xffffffff; mov ecx,eax; sub ebx,eax; M1: //вот здесь аналогичная проблема. переход нужен относительный // а я не знаю шо подставит сюда компиллер mov eax,[ebx]; xor eax,edx; mov [ebx],eax; add ebx,1; dec ecx; jnz M1; //вернее компиллер подставит это сюда pop ebx; mov eax,0xffffffff; sub ebx,eax; //вычисляем адрес перехода jmp ebx; //переходим (переход осуществляется за пределы процедуры - назад до ее начала в мое частном случае) ret; то есть, если данный код будет располагаться в случайном месте памяти, оно будет работать правильно? может я просто пересидел на си? дело в том что я пока еще не могу проверить его работоспособность
Вот уж не знаю. То, что после pop ebx в ebx будет текущий адрес метки а1 это 100%, а разбираться в твоих хитрых махинациях с 0xffffffff и sub ebx,eax как-то желания нет. Надеюсь ты учтешь добавление команд call+pop в расчетах дельты
EIP можно получить так: Код (Text): push 00900008h push 0c224048bh call esp nop ;теперь в eax адрес команды nop Надеюсь поможет
someone Джамп из процедуры в другое место есть плохой стиль (если только не дает очень сильных плюсов). Почему бы вам не подумать, как переделать алгоритм, чтобы этого не требовалось? А задачку решать просто для развития.
На C кстати тоже можно писать базонезависимый код. См. статью от Cr4sh http://hellknights.void.ru/research.php там пример есть.
y4eNick И что ? Тот же call, только еще придется VirtualProtect для натеги вызвать, т.к. с современными компами с их хардварными DEP-ами лучше не шутить )