У меня как у новичка,часто возникает такой вопрос каким можно наиболее удобным способом сохранить те или иные регистры перед вызовом WinApi функции или любой другой функции из другой DLL-библиотеки,в тех или иных алгоритмах использую регистры для хранение тех или значений,изменение этих ранее подготовленных регистров становится причиной проблем.
стёк менять не желательно, я эти регистры использую для другого и не собираюсь передавать через них аргументы
pushad/popad. Если апя возвращает булеву переменную можно сравнение перед popad'ом вставить, а после него условный переход. Другая уловка - вписать в макрос stdcall нужные регистры после аргументов, после вызова pop'нуть, но это чисто ради красоты в исходнике.
f13nd, единственный вариант который мне в голову приходит,так это создавать переменные, а затем сохранять в этих пременных значения регистров перед вызовом функции,но мне это кажется не удобным
Чтобы был смысл так делать, значение должно использоваться многократно между пересылками в память и обратно.
Если ты такой стека-фоб и у тебя может работать не один поток, то не просто "статические" переменные, а thread-local переменные.
Ну типа это ход конем: спасать значение регистра от пожирания одной апёй, скармливая его другой апе, которая похоронит все остальные несохраненные значения регистров.
Далеко не обязательно. Ты можешь выделить буферы для сохранения контекста на куче для каждого потока и держать указатель на буфер на стеке потока. Это по сути тоже будет локальной для потока переменной. Можешь руками в TEB лазить и обойтись без вызова TLS'ых апишек, если легких путей не ищешь.
А выигрыш тогда в чем, если и там и там память, адресуемая по базе в регистре? Ты как крелк, сам с чего-то решил, что нужны "статические" переменные и сам себе дал совет как их реализовать.
Чтобы не держать контекст на стеке, человек же не хочет на стеке. Я, как и любой другой магл, хочу казаться спецом, это нормально.
"На стеке" подразумевает манипуляции с верхушкой стека, то есть пуши и попы, но в х64 чаще всего стек-фрейм по rsp адресуется (то, под чего в х32 обычно используется ebp). Это загадочное адресное пространство, где хранятся локальные переменные в процедурах у цэшников.
Если не собираетесь передавать аргументы через регистры, то х32 что-ли приложение? Тогда pusha/popa ваш вариант. Просто можно пушить не в системный стек, а создать фиктивный (например в секции-данных), и перед pusha записать его адрес в ESP. Это избавит от нудного сохранения/восстановления каждого регистра в переменные. Правда х64 не поддерживает pusha, поэтому там только ручками. Примерно так.. Code (ASM): format pe gui entry start include 'win32ax.inc' ;//---------- .data fp dq 202307.158739 align 16 frame rb 128 ;// фиктивный стек newStack dd 0 ;// указатель на его макушку buff db 0 ;//---------- .code start: mov ebp,esp mov esp,newStack pusha ;// сохраняем сразу все регистры в "переменные" mov [newStack],esp mov esp,ebp ;// здесь что-то делаем.. cinvoke vsprintf,buff,<'Float = %lf',0>,fp invoke MessageBox,0,buff,<'Win32 Stack',0>,0 mov ebp,esp mov esp,[newStack] popa ;// восстанавливаем регистры mov esp,ebp invoke ExitProcess,0 ;//---------- section '.idata' import data readable library msvcrt,'msvcrt.dll',kernel32,'kernel32.dll',user32,'user32.dll' import msvcrt,vsprintf,'vsprintf' include 'api\kernel32.inc' include 'api\user32.inc'
Marylin, вот эта строчка вашего кода,тут где то Инди писал что нельзя переключить стёк на произвольный адрес,как вообще система отреагирует на то что я перезаписываю адрес указателя стёка ? Code (Text): .code mov esp,newStack --- Сообщение объединено, Aug 5, 2023 --- а если функция принимает например 5 аргументов,эти 5 аргументов передам через стёк,а вот 6 аргументом я положу в стёк нужный мне регистр,такой вариант сработает ?
моя Win7 x64 нормально реагирует, и код выше тому подтверждение, а вообще почитайте КК "Ассемблерные извращения - натягиваем стек" - там всё расписано. фрагмент статьи лежит здесь: https://evilfingers.com/publications/research_RU/asm-stack-hck.pdf