Работаю с четырьмя массивами, их нужно по быстрому и произвольно индексировать, регистров нормальных не хватает, для трех массивов использую базы ebp, esi, edi, ну а для четвертого использую esp. Типа mov eax, [esp + ecx*4] Перед запуском процедуры выполнил push esp... Шутка!!! =))) Заховал ESP в статическую ячейку, ну а потом ясен глаз восстановил... А теперь вопрос! Опасно ли такое нецелевое использование ESP для данных и для Винды в целом??? На первый взгляд все работает...
mov rEsp, esp [если здесь нет явного ображщения к стеку и вызова процедур, а так же переходов веущих за предел этого блока, то неопасно] mov esp,rEsp
А когда они разрешены? (если не ковырять отладчиком уровня ядра) А моя прога просто пользовательская без всяких привелегий... И вообще, организацию разделения доступа в памяти представляю смутно, но наверное у каждой запущенной проги или процесса своя виртуальная вершина стека?
Вопрос стоит так, если прога на каком-нибудь участке явно не использует стек или вызов функций, то может ли Винда или другая ОС, или runtime-библиотека, или прерывания или системные процессы положить что-нибудь незаметно в стек? А сам я от ESP отказался. Просто слил два массива вместе и база у них теперь одна, а смещение заранее известно. Береженого бог бережет, сказала монашка про незаряженное ружье... =)))
Если возникнет исключение, то возникнут большие проблемы. С другой стороны, ты их все равно не перехватываешь, раз esp используешь...
>> Вопрос стоит так, если прога на каком-нибудь участке явно не использует стек или вызов функций, то может ли Винда или другая ОС, или runtime-библиотека, или прерывания или системные процессы положить что-нибудь незаметно в стек? DOS может ОС защищённого режима - нет. "Незаметно" происходят только прерывания и исключения, в винде и всех прочих ОС защищённого режима они обрабатываются в ring0. При переключении и возврате из ring0 пользовательский стек не используется, используется стек ядра, к которому ты доступа не имеешь. Иначе любой пользователь, испортив свой стек, мог бы нарушить работу всей ОС.
sergh Ну.. надо конечно попробовать, но вряд ли исключение корректно обработается в ntdll.KiUserExceptionDispatcher если пользовательский стек разрушен. Скорее всего рухнет сам процесс и все..
Так как esp будет указывать все-таки на рабочую область памяти, то все-таки поток не упадет, но вот данные для расчетов подпортятся. Кстати, вирусы любят пользоваться чужим стеком для своих нужд. Поэтому вопрос стоит так - насколько критичны результаты расчета? Я предлагаю сделать так: 1) обьявить переменную 2) использовать xchg для обмена значения регистра и переменной. Более тормознуто, зато безопасно.
Вот код, который показывает, использует ли Винда пользовательский стек. Стоял на голове, стучал по клаве, елозил крысой, закрывал-открывал форточки, вывод один - не использует, не портит! Код (Text): function TestStack:Cardinal; asm push ebx // этого требует соглашение о регистрах mov ebx,$12345678 push ebx pop ebx // теперь на -1 этаже стека - 12345678h mov edx,3 // внешний цикл, чтоб подольше было @L2: mov ecx,$FFFFFFFF // внутренний цикл @L1: nop nop nop nop nop loop @L1 dec edx jnz @L2 xor eax,eax // возвращаем 0, если стек подпорчен mov edx,1 cmp ebx,[esp-4] cmove eax,edx // возвращаем 1, если все OK pop ebx end; К искажениям очень критичны, а тормоза недопустимы. Как я уже сказал, проблему индексирования массивов я решил расположив их сплошняком в памяти, при этом один базовый регистр высвободился и от esp несмотря ни на что я отказался, обошелся одним базовым регистром для двух массивов, mov eax,[edi + ecx*4] - из первого массива add eax,[edi + ecx*4 + смещение ] - из второго массива
persicum Ты не понял о чём тебе говорили про исключения. Ясно дело, что в твоём примере ничего не испортится. А вот если поставить seh изменить esp и вызвать исключение, то х.з. что получится. Кому не лень, тот проверит И, надеюсь, выложит результаты. Имхо Great прав, на счёт того, что процес рухнет.
Проверил Простой пример на FASM: Код (Text): include 'win32ax.inc' .code ; ; Точка входа ; start: ; Ставим SEH обработчик push handler push dword [fs:0] mov dword [fs:0], esp ; Стираем ESP xor esp, esp ; Генерируем исключение. Будет вызван handler xor eax, eax mov eax, [eax] ; .. сюда полюбому уже не дойдем .. ; ; SEH обработчик ; handler: ; Если Windows действительно насрать на ESP и она ставит свой, тогда этот код вызова MessageBox выполнится успешно ; и мы увидим окошко. Если нет - возникнет исключение в SEH-обработчике (здесь) и программа вылетит без всяких предупреждений. invoke MessageBox, HWND_DESKTOP, "Handler executed successfully", "SEH & ESP test", MB_ICONINFORMATION ; Если добрались до сюда - значит все ок.. завершаемся invoke ExitProcess, 0 .end start Если закомментировать XOR ESP, ESP то месаж бокс показывается успешно, а если оставить - программа вылетает в результате того, что винда пытается использовать испорченный стек потока. Олька при выполнении MOV DWORD PTR EAX, [EAX] говорит что Debugged program was unable to process the exception. Бряк на KiUserExceptionDispatcher так и не сработал. Делаем выводы...
А какая разница? Я не про это говорю. Можно и не на стеке - я ESP порчу потом это раз, а два - от того, что я испорчу ESP, страницы по адресу [FS:0] никуда не денутся и обработчик можно вынуть будет винде спокойно.
Да при чем тут в стеке- не в стеке? Тут вопрос про другое, используется ли стек потока во время возникновения исключения системными механизмами винды. Судя по всему да - если убрать XOR ESP, ESP то все ок. А где лежит обработчик - не суть важно. В принципе можно сделать и так: Код (Text): .data se_member dd 0, handler .code mov eax, [fs:0] mov [se_member], eax mov dword [fs:0], se_member .... UPD: Упс... не выходит =) Видимо и правда только в стеке можно
Если в хрюше, то софтварный DEP рулит - [fs:0] должен указывать обязательно на стэк, а сам обработчик наоборот не должен лежать в стэке. Проверка осуществляется по TIB.StackBase\StackLimit, так что при желании можно и над ними поизвращаться